Adamw has submitted this change and it was merged. Change subject: Initial Version of Twig L10N Filters ......................................................................
Initial Version of Twig L10N Filters Adding numeric and currency filters that are aware of locale. Replacing https://gerrit.wikimedia.org/r/#/c/53653/ Change-Id: I0e1fcd46b2f1caf182ef74c452417d487b3b66dc --- A sites/all/modules/wmf_common/twigext_l10n/CldrData.php A sites/all/modules/wmf_common/twigext_l10n/TwigLocalization.php A sites/all/modules/wmf_common/twigext_l10n/tests/TwigLocalizationTest.test A sites/all/modules/wmf_common/twigext_l10n/tests/twigext_l10n_tests.info A sites/all/modules/wmf_common/twigext_l10n/tests/twigext_l10n_tests.module 5 files changed, 849 insertions(+), 0 deletions(-) Approvals: Adamw: Verified; Looks good to me, approved diff --git a/sites/all/modules/wmf_common/twigext_l10n/CldrData.php b/sites/all/modules/wmf_common/twigext_l10n/CldrData.php new file mode 100644 index 0000000..e31179e --- /dev/null +++ b/sites/all/modules/wmf_common/twigext_l10n/CldrData.php @@ -0,0 +1,484 @@ +<?php +/** + * CLDR data file, CLDR date: $Revision: 7846 $ - $Date: 2012-10-15 10:23:41 -0700 (Mon, 15 Oct 2012) $ + */ +class CldrData { + /** @var array array(ISO code => array(decimal digits, rounding digits)) */ + public static $currencyData = array( + '*' => array(2, 0), + 'ADP' => array(0, 0), + 'AFN' => array(0, 0), + 'ALL' => array(0, 0), + 'AMD' => array(0, 0), + 'BHD' => array(3, 0), + 'BIF' => array(0, 0), + 'BYR' => array(0, 0), + 'CHF' => array(2, 5), + 'CLF' => array(0, 0), + 'CLP' => array(0, 0), + 'COP' => array(0, 0), + 'CRC' => array(0, 0), + 'DJF' => array(0, 0), + 'ESP' => array(0, 0), + 'GNF' => array(0, 0), + 'GYD' => array(0, 0), + 'HUF' => array(0, 0), + 'IDR' => array(0, 0), + 'IQD' => array(0, 0), + 'IRR' => array(0, 0), + 'ISK' => array(0, 0), + 'ITL' => array(0, 0), + 'JOD' => array(3, 0), + 'JPY' => array(0, 0), + 'KMF' => array(0, 0), + 'KPW' => array(0, 0), + 'KRW' => array(0, 0), + 'KWD' => array(3, 0), + 'LAK' => array(0, 0), + 'LBP' => array(0, 0), + 'LUF' => array(0, 0), + 'LYD' => array(3, 0), + 'MGA' => array(0, 0), + 'MGF' => array(0, 0), + 'MMK' => array(0, 0), + 'MNT' => array(0, 0), + 'MRO' => array(0, 0), + 'MUR' => array(0, 0), + 'OMR' => array(3, 0), + 'PKR' => array(0, 0), + 'PYG' => array(0, 0), + 'RSD' => array(0, 0), + 'RWF' => array(0, 0), + 'SLL' => array(0, 0), + 'SOS' => array(0, 0), + 'STD' => array(0, 0), + 'SYP' => array(0, 0), + 'TMM' => array(0, 0), + 'TND' => array(3, 0), + 'TRL' => array(0, 0), + 'TZS' => array(0, 0), + 'UGX' => array(0, 0), + 'UZS' => array(0, 0), + 'VND' => array(0, 0), + 'VUV' => array(0, 0), + 'XAF' => array(0, 0), + 'XOF' => array(0, 0), + 'XPF' => array(0, 0), + 'YER' => array(0, 0), + 'ZMK' => array(0, 0), + 'ZWD' => array(0, 0) + ); + + /** @var array array(ISO code => array(array(grouping), positive_currency_string, negative_currency_string)) */ + public static $localeNumberFormat = array( + '*' => array(array(), '$1 $2', '-$1 $2'), + 'aa' => array(array(3), '$1$2', '-$1$2'), + 'af' => array(array(3), '$1$2', '($1$2)'), + 'af_NA' => array(array(3), '$1 $2', '-$1 $2'), + 'agq' => array(array(3), '$2$1', '-$2$1'), + 'ak' => array(array(3), '$1$2', '-$1$2'), + 'am' => array(array(3), '$1$2', '($1$2)'), + 'ar' => array(array(3), '$1 $2', '$1 $2-'), + 'ar_QA' => array(array(), '$1$2', '-$1$2'), + 'ar_SA' => array(array(), '$1$2', '-$1$2'), + 'ar_SY' => array(array(), '$1$2', '-$1$2'), + 'ar_TN' => array(array(), '$1$2', '-$1$2'), + 'ar_YE' => array(array(), '$1$2', '-$1$2'), + 'as' => array(array(2, 3), '$1 $2', '-$1 $2'), + 'asa' => array(array(3), '$2 $1', '-$2 $1'), + 'ast' => array(array(3), '$2 $1', '-$2 $1'), + 'az' => array(array(3), '$1 $2', '-$1 $2'), + 'az_Cyrl' => array(array(3), '$1 $2', '-$1 $2'), + 'bas' => array(array(3), '$2 $1', '-$2 $1'), + 'be' => array(array(3), '$1$2', '-$1$2'), + 'bem' => array(array(3), '$1$2', '($1$2)'), + 'bez' => array(array(3), '$2$1', '-$2$1'), + 'bg' => array(array(3), '$2 $1', '-$2 $1'), + 'bm' => array(array(3), '$1$2', '($1$2)'), + 'bn' => array(array(2, 3), '$2$1', '($2$1)'), + 'bo' => array(array(3), '$1 $2', '-$1 $2'), + 'brx' => array(array(2, 3), '$1 $2', '-$1 $2'), + 'bs_Cyrl' => array(array(3), '$2 $1', '-$2 $1'), + 'byn' => array(array(3), '$1$2', '-$1$2'), + 'ca' => array(array(3), '$1$2', '($1$2)'), + 'cgg' => array(array(3), '$1$2', '-$2$1'), + 'chr' => array(array(3), '$1$2', '($1$2)'), + 'cs' => array(array(3), '$2 $1', '-$2 $1'), + 'cy' => array(array(3), '$1$2', '-$1$2'), + 'da' => array(array(3), '$2 $1', '-$2 $1'), + 'dav' => array(array(3), '$1$2', '($1$2)'), + 'de' => array(array(3), '$2 $1', '-$2 $1'), + 'de_AT' => array(array(3), '$1 $2', '-$1 $2'), + 'de_CH' => array(array(3), '$1 $2', '$1-$2'), + 'de_LI' => array(array(3), '$1 $2', '-$1 $2'), + 'dje' => array(array(3), '$2$1', '-$2$1'), + 'dua' => array(array(3), '$2 $1', '-$2 $1'), + 'dyo' => array(array(3), '$2 $1', '-$2 $1'), + 'dz' => array(array(2, 3), '$1$2', '-$1$2'), + 'ebu' => array(array(3), '$1$2', '($1$2)'), + 'ee' => array(array(3), '$1$2', '($1$2)'), + 'el' => array(array(3), '$2 $1', '-$2 $1'), + 'el_CY' => array(array(3), '$1$2', '-$1$2'), + 'en' => array(array(3), '$1$2', '($1$2)'), + 'en_150' => array(array(3), '$2 $1', '-$2 $1'), + 'en_BE' => array(array(3), '$2 $1', '-$2 $1'), + 'en_BW' => array(array(3), '$1$2', '-$1$2'), + 'en_BZ' => array(array(3), '$1$2', '-$1$2'), + 'en_GB' => array(array(3), '$1$2', '-$1$2'), + 'en_HK' => array(array(3), '$1$2', '($1$2)'), + 'en_IN' => array(array(2, 3), '$1 $2', '-$1 $2'), + 'en_JM' => array(array(3), '$1$2', '-$1$2'), + 'en_NA' => array(array(3), '$1$2', '-$1$2'), + 'en_PK' => array(array(2, 3), '$1 $2', '-$1 $2'), + 'en_SG' => array(array(3), '$1$2', '($1$2)'), + 'en_TT' => array(array(3), '$1$2', '-$1$2'), + 'en_US_POSIX' => array(array(), '$1 $2', '-$1 $2'), + 'en_ZW' => array(array(3), '$1$2', '-$1$2'), + 'es' => array(array(3), '$2 $1', '-$2 $1'), + 'es_419' => array(array(3), '$1$2', '-$1$2'), + 'es_CL' => array(array(3), '$1$2', '$1-$2'), + 'es_EC' => array(array(3), '$1$2', '$1-$2'), + 'es_GQ' => array(array(3), '$1$2', '-$1$2'), + 'es_PY' => array(array(3), '$1 $2', '$1 -$2'), + 'es_UY' => array(array(3), '$1 $2', '($1 $2)'), + 'es_VE' => array(array(3), '$1$2', '$1-$2'), + 'et' => array(array(), '$2$1', '($2$1)'), + 'eu' => array(array(3), '$2 $1', '($2 $1)'), + 'ewo' => array(array(3), '$2 $1', '-$2 $1'), + 'fa' => array(array(3), '$1$2', '($1$2)'), + 'ff' => array(array(3), '$2 $1', '-$2 $1'), + 'fi' => array(array(3), '$2 $1', '-$2 $1'), + 'fil' => array(array(3), '$1$2', '($1$2)'), + 'fo' => array(array(3), '$1$2', '$1-$2'), + 'fr' => array(array(3), '$2 $1', '($2 $1)'), + 'fr_CH' => array(array(3), '$1 $2', '$1-$2'), + 'fur' => array(array(3), '$1 $2', '-$1 $2'), + 'ga' => array(array(3), '$1$2', '-$1$2'), + 'gd' => array(array(3), '$1$2', '($1$2)'), + 'gl' => array(array(3), '$1$2', '($1$2)'), + 'gsw' => array(array(3), '$2 $1', '-$2 $1'), + 'gu' => array(array(3), '$1$2', '($1$2)'), + 'guz' => array(array(3), '$1$2', '($1$2)'), + 'gv' => array(array(3), '$1$2', '-$1$2'), + 'ha' => array(array(3), '$1 $2', '-$1 $2'), + 'haw' => array(array(3), '$1$2', '($1$2)'), + 'he' => array(array(3), '$2 $1', '-$2 $1'), + 'hi' => array(array(2, 3), '$1 $2', '-$1 $2'), + 'hr' => array(array(3), '$2 $1', '-$2 $1'), + 'hu' => array(array(3), '$2 $1', '-$2 $1'), + 'hy' => array(array(), '$2 $1', '-$2 $1'), + 'id' => array(array(3), '$1$2', '-$1$2'), + 'ig' => array(array(3), '$1$2', '($1$2)'), + 'is' => array(array(3), '$1$2', '($1$2)'), + 'it' => array(array(3), '$1 $2', '-$1 $2'), + 'it_CH' => array(array(3), '$1 $2', '$1-$2'), + 'ja' => array(array(3), '$1$2', '-$1$2'), + 'jgo' => array(array(3), '$1 $2', '-$1 $2'), + 'jmc' => array(array(3), '$1$2', '-$1$2'), + 'ka' => array(array(3), '$2 $1', '-$2 $1'), + 'kab' => array(array(3), '$2$1', '-$2$1'), + 'kam' => array(array(3), '$1$2', '($1$2)'), + 'kde' => array(array(3), '$1$2', '($1$2)'), + 'kea' => array(array(3), '$2$1', '-$2$1'), + 'khq' => array(array(3), '$2$1', '-$2$1'), + 'ki' => array(array(3), '$1$2', '($1$2)'), + 'kk' => array(array(3), '$2 $1', '-$2 $1'), + 'kl' => array(array(3), '$1$2', '$1-$2'), + 'kln' => array(array(3), '$1$2', '($1$2)'), + 'km' => array(array(3), '$1$2', '($1$2)'), + 'kn' => array(array(3), '$1$2', '($1$2)'), + 'ko' => array(array(3), '$1$2', '($1$2)'), + 'kok' => array(array(2, 3), '$1 $2', '-$1 $2'), + 'ks' => array(array(2, 3), '$1 $2', '-$1 $2'), + 'ksb' => array(array(3), '$2$1', '-$2$1'), + 'ksf' => array(array(3), '$2 $1', '-$2 $1'), + 'ksh' => array(array(3), '$2 $1', '-$2 $1'), + 'kw' => array(array(3), '$1$2', '-$1$2'), + 'lg' => array(array(3), '$2$1', '-$2$1'), + 'ln' => array(array(3), '$2 $1', '-$2 $1'), + 'lo' => array(array(3), '$1$2', '$1-$2'), + 'lt' => array(array(3), '$2 $1', '-$2 $1'), + 'lu' => array(array(3), '$2$1', '-$2$1'), + 'luo' => array(array(3), '$2$1', '-$2$1'), + 'luy' => array(array(3), '$1$2', '$1- $2'), + 'lv' => array(array(3), '$1$2', '($1$2)'), + 'mas' => array(array(3), '$1$2', '($1$2)'), + 'mer' => array(array(3), '$1$2', '($1$2)'), + 'mg' => array(array(3), '$1$2', '-$1$2'), + 'mgo' => array(array(3), '$1 $2', '-$1 $2'), + 'mk' => array(array(3), '$1 $2', '-$1 $2'), + 'ml' => array(array(2, 3), '$2$1', '-$2$1'), + 'mr' => array(array(3), '$1$2', '($1$2)'), + 'ms' => array(array(3), '$1$2', '($1$2)'), + 'ms_BN' => array(array(3), '$1 $2', '-$1 $2'), + 'mt' => array(array(3), '$1$2', '-$1$2'), + 'mua' => array(array(3), '$1$2', '($1$2)'), + 'my' => array(array(3), '$1 $2', '-$1 $2'), + 'naq' => array(array(3), '$1$2', '-$1$2'), + 'nb' => array(array(3), '$1 $2', '-$1 $2'), + 'nd' => array(array(3), '$1$2', '($1$2)'), + 'nl' => array(array(3), '$1 $2', '$1 $2-'), + 'nl_BE' => array(array(3), '$2 $1', '-$2 $1'), + 'nmg' => array(array(3), '$2 $1', '-$2 $1'), + 'nn' => array(array(3), '$2 $1', '-$2 $1'), + 'nr' => array(array(3), '$1$2', '-$1$2'), + 'nso' => array(array(3), '$1$2', '-$1$2'), + 'nus' => array(array(3), '$1$2', '($1$2)'), + 'nyn' => array(array(3), '$1$2', '-$2$1'), + 'om' => array(array(3), '$1$2', '-$1$2'), + 'or' => array(array(2, 3), '$1 $2', '-$1 $2'), + 'os' => array(array(3), '$1 $2', '-$1 $2'), + 'pa' => array(array(2, 3), '$1 $2', '-$1 $2'), + 'pl' => array(array(3), '$2 $1', '($2 $1)'), + 'ps' => array(array(3), '$2 $1', '-$2 $1'), + 'pt' => array(array(3), '$1$2', '($1$2)'), + 'pt_PT' => array(array(3), '$2 $1', '-$2 $1'), + 'rm' => array(array(3), '$2 $1', '-$2 $1'), + 'rn' => array(array(3), '$2$1', '-$2$1'), + 'ro' => array(array(3), '$2 $1', '-$2 $1'), + 'rof' => array(array(3), '$1$2', '-$1$2'), + 'root' => array(array(3), '$1 $2', '-$1 $2'), + 'ru' => array(array(3), '$2 $1', '-$2 $1'), + 'rwk' => array(array(3), '$2$1', '-$2$1'), + 'saq' => array(array(3), '$1$2', '($1$2)'), + 'sbp' => array(array(3), '$2$1', '-$2$1'), + 'se' => array(array(3), '$2 $1', '-$2 $1'), + 'seh' => array(array(3), '$2$1', '-$2$1'), + 'ses' => array(array(3), '$2$1', '-$2$1'), + 'sg' => array(array(3), '$1$2', '$1-$2'), + 'shi' => array(array(3), '$2$1', '-$2$1'), + 'shi_Latn' => array(array(3), '$2$1', '-$2$1'), + 'si' => array(array(2, 3), '$1 $2', '-$1 $2'), + 'sk' => array(array(3), '$2 $1', '-$2 $1'), + 'sl' => array(array(3), '$1$2', '($1$2)'), + 'sn' => array(array(3), '$1$2', '($1$2)'), + 'so' => array(array(3), '$1$2', '-$1$2'), + 'sq' => array(array(3), '$1$2', '-$1$2'), + 'sr' => array(array(3), '$2 $1', '-$2 $1'), + 'ss' => array(array(3), '$1$2', '-$1$2'), + 'ssy' => array(array(3), '$1$2', '-$1$2'), + 'st' => array(array(3), '$1$2', '-$1$2'), + 'sv' => array(array(3), '$2 $1', '-$2 $1'), + 'sw' => array(array(3), '$1$2', '($1$2)'), + 'sw_KE' => array(array(3), '$1$2', '-$1$2'), + 'swc' => array(array(3), '$1$2', '-$1$2'), + 'ta' => array(array(2, 3), '$1 $2', '-$1 $2'), + 'ta_MY' => array(array(3), '$1 $2', '-$1 $2'), + 'ta_SG' => array(array(3), '$1 $2', '-$1 $2'), + 'te' => array(array(3), '$1$2', '($1$2)'), + 'teo' => array(array(3), '$1$2', '($1$2)'), + 'th' => array(array(3), '$1$2', '($1$2)'), + 'ti' => array(array(3), '$1$2', '-$1$2'), + 'tig' => array(array(3), '$1$2', '-$1$2'), + 'tn' => array(array(3), '$1$2', '-$1$2'), + 'to' => array(array(3), '$1 $2', '-$1 $2'), + 'tr' => array(array(3), '$2 $1', '($2 $1)'), + 'ts' => array(array(3), '$1$2', '-$1$2'), + 'twq' => array(array(3), '$2$1', '-$2$1'), + 'tzm' => array(array(3), '$2 $1', '-$2 $1'), + 'uk' => array(array(3), '$2 $1', '-$2 $1'), + 'ur' => array(array(3), '$1$2', '-$1$2'), + 'ur_IN' => array(array(2, 3), '$1 $2', '-$1 $2'), + 'uz_Arab' => array(array(3), '$2 $1', '-$2 $1'), + 'vai' => array(array(3), '$1$2', '($1$2)'), + 'vai_Latn' => array(array(3), '$1$2', '($1$2)'), + 've' => array(array(3), '$1$2', '-$1$2'), + 'vi' => array(array(3), '$2 $1', '-$2 $1'), + 'vun' => array(array(3), '$1$2', '-$1$2'), + 'wal' => array(array(3), '$1$2', '-$1$2'), + 'xh' => array(array(3), '$1$2', '-$1$2'), + 'xog' => array(array(3), '$2 $1', '-$2 $1'), + 'yav' => array(array(3), '$2 $1', '($2 $1)'), + 'yo' => array(array(3), '$1$2', '($1$2)'), + 'zh' => array(array(3), '$1$2', '($1$2)'), + 'zh_Hans_HK' => array(array(3), '$1$2', '-$1$2'), + 'zh_Hans_MO' => array(array(3), '$1$2', '-$1$2'), + 'zh_Hans_SG' => array(array(3), '$1$2', '-$1$2'), + 'zh_Hant' => array(array(3), '$1$2', '-$1$2'), + 'zh_Hant_HK' => array(array(3), '$1$2', '($1$2)'), + 'zu' => array(array(3), '$1$2', '($1$2)') + ); + + /** @var array array(ISO code => array(decimal_char, group_char)) */ + public static $localCharacters = array( + '*' => array('.', ','), + 'af' => array(',', ' '), + 'agq' => array(',', ' '), + 'ak' => array('.', ','), + 'am' => array('.', ','), + 'ar' => array('.', ','), + 'ar_DZ' => array(',', '.'), + 'ar_LB' => array(',', '.'), + 'ar_LY' => array(',', '.'), + 'ar_MA' => array(',', '.'), + 'ar_MR' => array(',', '.'), + 'ar_TN' => array(',', '.'), + 'ast' => array(',', '.'), + 'az' => array(',', '.'), + 'az_Cyrl' => array(',', '.'), + 'bas' => array(',', ' '), + 'be' => array(',', ' '), + 'bg' => array(',', ' '), + 'bn' => array('.', ','), + 'bo' => array('.', ','), + 'br' => array(',', ' '), + 'brx' => array('.', ','), + 'bs' => array(',', '.'), + 'bs_Cyrl' => array(',', '.'), + 'ca' => array(',', '.'), + 'chr' => array('.', ','), + 'cs' => array(',', ' '), + 'cy' => array('.', ','), + 'da' => array(',', '.'), + 'de' => array(',', '.'), + 'de_CH' => array('.', '\''), + 'de_LI' => array('.', '\''), + 'dje' => array('.', ' '), + 'dua' => array(',', ' '), + 'dyo' => array(',', ' '), + 'dz' => array('.', ','), + 'el' => array(',', '.'), + 'en' => array('.', ','), + 'en_150' => array(',', '.'), + 'en_BE' => array(',', '.'), + 'en_ZA' => array(',', ' '), + 'eo' => array(',', ' '), + 'es' => array(',', '.'), + 'es_419' => array('.', ','), + 'es_AR' => array(',', '.'), + 'es_BO' => array(',', '.'), + 'es_CL' => array(',', '.'), + 'es_CO' => array(',', '.'), + 'es_CR' => array(',', '.'), + 'es_EC' => array(',', '.'), + 'es_PY' => array(',', '.'), + 'es_UY' => array(',', '.'), + 'es_VE' => array(',', '.'), + 'et' => array(',', ' '), + 'eu' => array(',', '.'), + 'ewo' => array(',', ' '), + 'fa' => array('.', ','), + 'ff' => array(',', ' '), + 'fi' => array(',', ' '), + 'fil' => array('.', ','), + 'fo' => array(',', '.'), + 'fr' => array(',', ' '), + 'fr_BE' => array('.', '.'), + 'fr_CH' => array('.', '\''), + 'fr_LU' => array('.', '.'), + 'fur' => array(',', '.'), + 'ga' => array('.', ','), + 'gd' => array('.', ','), + 'gl' => array(',', '.'), + 'gsw' => array('.', '’'), + 'gu' => array('.', ','), + 'ha' => array('.', ','), + 'he' => array('.', ','), + 'hi' => array('.', ','), + 'hr' => array(',', '.'), + 'hu' => array(',', ' '), + 'hy' => array(',', '.'), + 'ia' => array(',', '.'), + 'id' => array(',', '.'), + 'ii' => array('.', ','), + 'is' => array(',', '.'), + 'it' => array(',', '.'), + 'it_CH' => array('.', '\''), + 'ja' => array('.', ','), + 'jgo' => array(',', '.'), + 'ka' => array(',', '.'), + 'kab' => array(',', ' '), + 'kea' => array(',', '.'), + 'khq' => array('.', ' '), + 'kk' => array(',', ' '), + 'kkj' => array(',', '.'), + 'kl' => array(',', '.'), + 'km' => array(',', '.'), + 'kn' => array('.', ','), + 'ko' => array('.', ','), + 'ks' => array('.', ','), + 'ksf' => array(',', ' '), + 'ksh' => array(',', ' '), + 'ky' => array(',', ' '), + 'ln' => array(',', '.'), + 'lo' => array(',', '.'), + 'lt' => array(',', ' '), + 'lu' => array(',', '.'), + 'lv' => array(',', ' '), + 'mfe' => array('.', ' '), + 'mgh' => array(',', '.'), + 'mgo' => array('.', ','), + 'mk' => array(',', '.'), + 'ml' => array('.', ','), + 'mr' => array('.', ','), + 'ms' => array('.', ','), + 'ms_BN' => array(',', '.'), + 'mt' => array('.', ','), + 'mua' => array(',', '.'), + 'my' => array('.', ','), + 'nb' => array(',', ' '), + 'ne' => array('.', ','), + 'nl' => array(',', '.'), + 'nmg' => array(',', ' '), + 'nn' => array(',', ' '), + 'nnh' => array(',', '.'), + 'nr' => array(',', ' '), + 'nso' => array(',', ' '), + 'nus' => array('.', ','), + 'or' => array('.', ','), + 'os' => array(',', ' '), + 'pl' => array(',', ' '), + 'ps' => array(',', '.'), + 'pt' => array(',', '.'), + 'pt_PT' => array(',', ' '), + 'rm' => array('.', '’'), + 'rn' => array(',', '.'), + 'ro' => array(',', '.'), + 'root' => array('.', ','), + 'ru' => array(',', ' '), + 'rw' => array(',', '.'), + 'sbp' => array('.', ','), + 'se' => array(',', ' '), + 'seh' => array(',', '.'), + 'ses' => array('.', ' '), + 'sg' => array(',', '.'), + 'shi' => array(',', ' '), + 'shi_Latn' => array(',', ' '), + 'sk' => array(',', ' '), + 'sl' => array(',', '.'), + 'so' => array('.', ','), + 'sq' => array(',', ' '), + 'sr' => array(',', '.'), + 'sr_Latn' => array(',', '.'), + 'ss' => array(',', ' '), + 'st' => array(',', ' '), + 'sv' => array(',', ' '), + 'sw' => array('.', ','), + 'swc' => array(',', '.'), + 'ta' => array('.', ','), + 'te' => array('.', ','), + 'th' => array('.', ','), + 'tn' => array(',', ' '), + 'to' => array('.', ','), + 'tr' => array(',', '.'), + 'ts' => array(',', ' '), + 'twq' => array('.', ' '), + 'tzm' => array(',', ' '), + 'uk' => array(',', ' '), + 'ur' => array('.', ','), + 'uz' => array(',', ' '), + 'uz_Arab' => array(',', '.'), + 'uz_Latn' => array(',', ' '), + 'vai' => array('.', ','), + 'vai_Latn' => array('.', ','), + 've' => array(',', ' '), + 'vi' => array(',', '.'), + 'wae' => array(',', '’'), + 'wal' => array('.', '’'), + 'xh' => array(',', ' '), + 'yav' => array(',', ' '), + 'zh' => array('.', ','), + 'zh_Hant' => array('.', ','), + 'zu' => array('.', ',') + ); +} diff --git a/sites/all/modules/wmf_common/twigext_l10n/TwigLocalization.php b/sites/all/modules/wmf_common/twigext_l10n/TwigLocalization.php new file mode 100644 index 0000000..2b5088f --- /dev/null +++ b/sites/all/modules/wmf_common/twigext_l10n/TwigLocalization.php @@ -0,0 +1,255 @@ +<?php + +require_once( 'CldrData.php' ); + +/** + * Implements various localization filters: + * - Number format (1234.43 -> 1 234,43 .. 1,234.43) + * - Currency format (EUR 1234.43 -> €1,234.43 .. 1 234,43 €) + */ +class TwigLocalization extends Twig_Extension { + /** @var array Currency symbols keyed on ISO currency code, source http://www.xe.com/symbols.php */ + protected static $currency_symbols = array( + 'AFN' => '؋', + 'ANG' => 'ƒ', + 'ARS' => '$', + 'AUD' => '$', + 'AWG' => 'ƒ', + 'AZN' => 'ман', + 'BAM' => 'KM', + 'BBD' => '$', + 'BGN' => 'лв', + 'BMD' => '$', + 'BND' => '$', + 'BOB' => '$b', + 'BRL' => 'R$', + 'BSD' => '$', + 'BWP' => 'P', + 'BYR' => 'p.', + 'BZD' => 'BZ$', + 'CAD' => '$', + 'CHF' => 'CHF', + 'CLP' => '$', + 'CNY' => '¥', + 'COP' => '$', + 'CRC' => '₡', + 'CUP' => '₱', + 'CZK' => 'Kč', + 'DKK' => 'kr', + 'DOP' => 'RD$', + 'EEK' => 'kr', + 'EGP' => '£', + 'EUR' => '€', + 'FJD' => '$', + 'FKP' => '£', + 'GBP' => '£', + 'GGP' => '£', + 'GHC' => '¢', + 'GIP' => '£', + 'GTQ' => 'Q', + 'GYD' => '$', + 'HKD' => '$', + 'HNL' => 'L', + 'HRK' => 'kn', + 'HUF' => 'Ft', + 'IDR' => 'Rp', + 'ILS' => '₪', + 'IMP' => '£', + 'IRR' => '﷼', + 'ISK' => 'kr', + 'JEP' => '£', + 'JMD' => 'J$', + 'JPY' => '¥', + 'KGS' => 'лв', + 'KHR' => '៛', + 'KPW' => '₩', + 'KRW' => '₩', + 'KYD' => '$', + 'KZT' => 'лв', + 'LAK' => '₭', + 'LBP' => '£', + 'LKR' => '₨', + 'LRD' => '$', + 'LTL' => 'Lt', + 'LVL' => 'Ls', + 'MKD' => 'ден', + 'MNT' => '₮', + 'MUR' => '₨', + 'MXN' => '$', + 'MYR' => 'RM', + 'MZN' => 'MT', + 'NAD' => '$', + 'NGN' => '₦', + 'NIO' => 'C$', + 'NOK' => 'kr', + 'NPR' => '₨', + 'NZD' => '$', + 'OMR' => '﷼', + 'PAB' => 'B/.', + 'PEN' => 'S/.', + 'PHP' => '₱', + 'PKR' => '₨', + 'PLN' => 'zł', + 'PYG' => 'Gs', + 'QAR' => '﷼', + 'RON' => 'lei', + 'RSD' => 'Дин.', + 'RUB' => 'руб', + 'SAR' => '﷼', + 'SBD' => '$', + 'SCR' => '₨', + 'SEK' => 'kr', + 'SGD' => '$', + 'SHP' => '£', + 'SOS' => 'S', + 'SRD' => '$', + 'SVC' => '$', + 'SYP' => '£', + 'THB' => '฿', + 'TRL' => '₤', + 'TRY' => 'info', + 'TTD' => 'TT$', + 'TVD' => '$', + 'TWD' => 'NT$', + 'UAH' => '₴', + 'USD' => '$', + 'UYU' => '$U', + 'UZS' => 'лв', + 'VEF' => 'Bs', + 'VND' => '₫', + 'XCD' => '$', + 'YER' => '﷼', + 'ZAR' => 'R', + 'ZWD' => 'Z$' + ); + + /** + * Returns the name of the extension. + * + * @return string The extension name + */ + public function getName() { + return "Wikimedia Foundation -- Twig Localization"; + } + + /** + * Returns a list of filters to add to the existing list. + * + * @return array An array of filters + */ + public function getFilters() { + return array( + new Twig_SimpleFilter( 'l10n_currency', array( $this, 'l10n_currency' ) ), + new Twig_SimpleFilter( 'l10n_number', array( $this, 'l10n_number' ) ), + ); + } + + /** + * Localize a currency string, string is expected to be <ISO Code> <Non formatted number> + * Will transform the string by replacing the currency symbol, if available, + * formatting the number and re arranging the symbol/number as appropriate to the language. + * + * @param string $string <ISO Code> <Non formatted number [0-9]+[\.]?[0-9]*> + * @param string $locale Language to translate into, may be a locale (e.g. en_GB) + * + * @return string Transformed $string + */ + public static function l10n_currency( $string, $locale = '*' ) { + list( $currency, $amount ) = explode( ' ', $string, 2 ); + $amount = floatval( $amount ); + + $decimals = static::getFromCldrArray( CldrData::$currencyData, $currency, 0 ); + + if ( array_key_exists( $currency, static::$currency_symbols ) ) { + $currency = static::$currency_symbols[$currency]; + } + + if ( $amount > 0 ) { + $retval = static::getFromCldrArray( CldrData::$localeNumberFormat, $locale, 1 ); + } else { + $retval = static::getFromCldrArray( CldrData::$localeNumberFormat, $locale, 2 ); + $amount *= -1; // The format will take care of annunciation of +/- + } + + $retval = str_replace( '$1', $currency, $retval ); + $retval = str_replace( '$2', static::l10n_number( $amount, $decimals, $locale ), $retval ); + return $retval; + } + + /** + * Localize a number as defined by the given locale. + * + * @param string $string Number to format + * @param int $decimals Round to number of decimals + * @param string $locale Locale to format into + * + * @return string Transformed $string + */ + public static function l10n_number( $string, $decimals = 2, $locale = '*' ) { + list( $decPoint, $groupPoint ) = static::getFromCldrArray( CldrData::$localCharacters, $locale ); + $grouping = static::getFromCldrArray( CldrData::$localeNumberFormat, $locale, 0 ); + + // We don't want to use this function to actually subst in the characters because + // it's not multibyte safe. + // https://bugs.php.net/bug.php?id=64424 + $string = number_format( floatval( $string ), $decimals, '.', '' ); + + $count = 0; + if ( $decimals > 0 ) { + $i = strpos( $string, '.' ) - 1; + $newstring = $decPoint . substr( $string, $i + 2 ); + } else { + $i = strlen( $string ) - 1; + $newstring = ''; + } + + // Now add the group separators + if ( count( $grouping ) > 0 ) { + $groupVal = array_pop( $grouping ); + while ( $i >= 0 ) { + if ( ( $count != 0 ) && ( $count == $groupVal ) ) { + $newstring = $string[$i] . $groupPoint . $newstring; + $count = 0; + if ( count( $grouping ) > 0 ) { + $groupVal = array_pop( $grouping ); + } + } else { + $newstring = $string[$i] . $newstring; + } + $i--; + $count++; + } + } else { + $newstring = substr( $string, 0, $i + 1 ) . $newstring; + } + + return $newstring; + } + + /** + * Gets the nearest locale value from CLDR + * + * @param array $ary The array to operate on + * @param string $locale Locale string, like en or en_US + * @param int $index If a specific sub array index is required; set this to it + * + * @return mixed Contents of array at key $locale + */ + protected static function getFromCldrArray( &$ary, $locale, $index = null ) { + $split = explode( '_', $locale ); + + if ( array_key_exists( $locale, $ary ) ) { + $retval = $ary[$locale]; + } elseif ( ( count( $split ) == 2 ) && ( array_key_exists( $split[0], $ary ) ) ) { + $retval = $ary[$split[0]]; + } else { + $retval = $ary['*']; + } + + if ( $index !== null ) { + return $retval[$index]; + } else { + return $retval; + } + } +} diff --git a/sites/all/modules/wmf_common/twigext_l10n/tests/TwigLocalizationTest.test b/sites/all/modules/wmf_common/twigext_l10n/tests/TwigLocalizationTest.test new file mode 100644 index 0000000..688fe3c --- /dev/null +++ b/sites/all/modules/wmf_common/twigext_l10n/tests/TwigLocalizationTest.test @@ -0,0 +1,103 @@ +<?php + +class TwigLocalizationTest extends DrupalWebTestCase { + public function setUp() { + parent::setUp(); + + // Get twig + if ( !class_exists( 'Twig_Autoloader', false ) ) { + $twig_include = '/mnt/twig/current/lib/Twig/Autoloader.php'; + if( !file_exists( $twig_include ) ) { + throw new Exception( "Twig libraries not found. Path checked: $twig_include" ); + } + require_once $twig_include; + Twig_Autoloader::register(); + + require_once drupal_get_path( 'module', 'wmf_common' ) . '/twigext_l10n/TwigLocalization.php'; + } + } + + public static function getInfo() { + return array( + 'name' => 'Twig Localization', + 'group' => 'Localization & Internationalization', + 'description' => 'Tests twig filters', + ); + } + + public function testCurrencyFilter() { + $this->assertEqual( + TwigLocalization::l10n_currency( "USD 1234.56", 'en' ), + "$1,234.56", + "L10n Currency: USD Positive in locale en" + ); + + $this->assertEqual( + TwigLocalization::l10n_currency( "USD -1234.56", 'en' ), + "($1,234.56)", + "L10n Currency: USD negative in locale en" + ); + } + + public function testNumericFilter() { + $this->assertEqual( + TwigLocalization::l10n_number( "1234567.89123" ), + "1234567.89", + "l10n Numeric: * locale with two decimals" + ); + + $this->assertEqual( + TwigLocalization::l10n_number( "1234567.89123", 0 ), + "1234568", + "l10n Numeric: * locale with no decimals" + ); + + $this->assertEqual( + TwigLocalization::l10n_number( "1234567.89123", 2, 'en' ), + "1,234,567.89", + "l10n Numeric: en locale with two decimals" + ); + + $this->assertEqual( + TwigLocalization::l10n_number( "1234567.89123", 2, 'en_ZA' ), + "1\xC2\xA0234\xC2\xA0567,89", + "l10n Numeric: en_ZA locale with two decimals" + ); + + $this->assertEqual( + TwigLocalization::l10n_number( "1234567.89123", 2, 'de_XX' ), + "1.234.567,89", + "l10n Numeric: de_XX (fallback test) locale with two decimals" + ); + + $this->assertEqual( + TwigLocalization::l10n_number( "1234567.89523", 2, 'xx_XX' ), + "1234567.90", + "l10n Numeric: xx_XX (complete fallback test, round up) locale with two decimals" + ); + + $this->assertEqual( + TwigLocalization::l10n_number( "91234567.89123", 2, 'as' ), + "9,12,34,567.89", + "l10n Numeric: as locale (2,3 grouping test) locale with two decimals" + ); + + $this->assertEqual( + TwigLocalization::l10n_number( "91234567.89123", 0, 'as' ), + "9,12,34,568", + "l10n Numeric: as locale (2,3 grouping test) locale with no decimals" + ); + + $this->assertEqual( + TwigLocalization::l10n_number( "-34567.89123", 0, 'am' ), + "-34,568", + "l10n Numeric: am locale (negative formatting) locale with no decimals" + ); + + $this->assertEqual( + TwigLocalization::l10n_number( "-34567.89523", 2, 'am' ), + "-34,567.90", + "l10n Numeric: am locale (negative formatting, round up) locale with no decimals" + ); + } +} diff --git a/sites/all/modules/wmf_common/twigext_l10n/tests/twigext_l10n_tests.info b/sites/all/modules/wmf_common/twigext_l10n/tests/twigext_l10n_tests.info new file mode 100644 index 0000000..9901957 --- /dev/null +++ b/sites/all/modules/wmf_common/twigext_l10n/tests/twigext_l10n_tests.info @@ -0,0 +1,7 @@ +name = Twig Localization Test Cases +description = Tests the twigext_l10n code +core = 6.x +dependencies[] = wmf_common +package = wmf_common +files[] = TwigLocalizationTest.test +files[] = ../TwigLocalization.php \ No newline at end of file diff --git a/sites/all/modules/wmf_common/twigext_l10n/tests/twigext_l10n_tests.module b/sites/all/modules/wmf_common/twigext_l10n/tests/twigext_l10n_tests.module new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sites/all/modules/wmf_common/twigext_l10n/tests/twigext_l10n_tests.module -- To view, visit https://gerrit.wikimedia.org/r/63252 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I0e1fcd46b2f1caf182ef74c452417d487b3b66dc Gerrit-PatchSet: 2 Gerrit-Project: wikimedia/fundraising/crm Gerrit-Branch: master Gerrit-Owner: Mwalker <[email protected]> Gerrit-Reviewer: Adamw <[email protected]> _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
