├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── composer.json └── src ├── Concerns ├── Collapse.php ├── NumberResolver.php ├── TripletTransformer.php └── TripletsConverter.php ├── Dictionary.php ├── DictionaryInterface.php ├── SouthDictionary.php └── Transformer.php /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | Tất cả lịch sử tiến trình phát triển thư viện 4 | 5 | # 1.3.0 6 | 7 | - Cho phép thay đổi cách đọc phần thập phân. 8 | 9 | # 1.2.1 10 | 11 | - Hổ trợ PHP8. 12 | 13 | # 1.2.0 14 | 15 | - Xóa phương thức trừu tượng `getDictionary` trong `Concerns\TripletTransformer`. 16 | - Tổ chức lại cấu trúc code. 17 | 18 | # 1.1.0 19 | 20 | - Xóa phương thức `resolve` trong `Transfomer`. 21 | - Tổ chức lại cấu trúc code. 22 | 23 | # 1.0.5 24 | 25 | - Thêm concern `NumberResolver`. 26 | 27 | # 1.0.4 28 | 29 | - Cập nhật verify input tại phương thức `resolve` của lớp `Transfomer`. 30 | 31 | # 1.0.3 32 | 33 | - Sửa lỗi khi chuyển đổi phân số âm có số nguyên là 0. 34 | 35 | # 1.0.2 36 | 37 | - Sửa lỗi khi chuyển đổi phân số có số nguyên là 0. 38 | 39 | # 1.0.1 40 | 41 | - Sửa đơn vị tính trong từ điển miền Nam. 42 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) PHP Viet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

Number To Words

6 |
7 |

8 | Latest version 9 | Build status 10 | Quantity score 11 | StyleCI 12 | Total download 13 | License 14 |

15 |

16 | 17 | ## Thông tin 18 | 19 | Thư viện hổ trợ chuyển đổi số sang chữ số Tiếng Việt. 20 | 21 | ## Cài đặt 22 | 23 | Cài đặt Number To Words thông qua [Composer](https://getcomposer.org): 24 | 25 | ```bash 26 | composer require phpviet/number-to-words 27 | ``` 28 | 29 | ## Cách sử dụng 30 | 31 | ### Tích hợp sẵn trên các framework phổ biến hiện tại 32 | 33 | - [`Laravel`](https://github.com/phpviet/laravel-number-to-words) 34 | - [`Symfony`](https://github.com/phpviet/symfony-number-to-words) 35 | - [`Yii`](https://github.com/phpviet/yii-number-to-words) 36 | 37 | hoặc nếu bạn muốn sử dụng không dựa trên framework thì tiếp tục xem tiếp. 38 | 39 | ### Các tính năng của thư viện: 40 | 41 | - [`Chuyển đổi số sang chữ số`](#Chuyển-đổi-số-sang-chữ-số) 42 | - [`Chuyển đổi số sang tiền tệ`](#Chuyển-đổi-số-sang-tiền-tệ) 43 | - [`Thay cách đọc số`](#Thay-cách-đọc-số) 44 | 45 | ### Chuyển đổi số sang chữ số 46 | 47 | Thư viện cung cấp cho chúng ta lớp `PHPViet\NumberToWords\Transformer` để thực hiện việc chuyển đổi 48 | thông qua phương thức `toWords` của đối tượng: 49 | 50 | ```php 51 | 52 | use PHPViet\NumberToWords\Transformer; 53 | 54 | $transformer = new Transformer(); 55 | 56 | // âm năm 57 | $transformer->toWords(-5); 58 | 59 | // năm 60 | $transformer->toWords(5); 61 | 62 | // năm phẩy năm 63 | $transformer->toWords(5.5); 64 | 65 | // mười lăm 66 | $transformer->toWords(15); 67 | 68 | // một trăm linh năm 69 | $transformer->toWords(105); 70 | 71 | // bốn 72 | $transformer->toWords(4); 73 | 74 | // mười bốn 75 | $transformer->toWords(14); 76 | 77 | // hai mươi tư 78 | $transformer->toWords(24); 79 | 80 | // một trăm ba mươi tư 81 | $transformer->toWords(134); 82 | 83 | // một 84 | $transformer->toWords(1); // một 85 | 86 | // mười một 87 | $transformer->toWords(11); 88 | 89 | // hai mươi mốt 90 | $transformer->toWords(21); 91 | 92 | // một trăm nghìn không trăm hai mươi mốt. 93 | $transformer->toWords(100021); 94 | 95 | // một trăm ba mươi mốt triệu không trăm năm mươi nghìn không trăm ba mươi lăm 96 | $transformer->toWords(131050035); 97 | 98 | ``` 99 | 100 | ### Chuyển đổi số sang tiền tệ 101 | 102 | Cũng như cách sử dụng của chuyển số sang chữ số ta cũng sử dụng lớp `PHPViet\NumberToWords\Transformer` 103 | để thực thi tác vụ: 104 | 105 | ```php 106 | 107 | use PHPViet\NumberToWords\Transformer; 108 | 109 | $transformer = new Transformer(); 110 | 111 | // năm triệu sáu trăm chín mươi nghìn bảy trăm đồng 112 | $transformer->toCurrency(5690700); 113 | 114 | // chín mươi lăm triệu năm trăm nghìn hai trăm đồng 115 | $transformer->toCurrency(95500200); 116 | 117 | // tám trăm năm mươi tư triệu chín trăm đồng 118 | $transformer->toCurrency(854000900); 119 | 120 | ``` 121 | Trong một số loại tiền tệ, bạn cần thay đổi cách đọc theo đơn vị quy đổi, ví dụ 1 đô = 100 xen 122 | ```php 123 | use PHPViet\NumberToWords\Transformer; 124 | 125 | // Đặt số chữ số phần thập phân (tham số đầu tiên Dictionary có thể null) 126 | $transformer = new Transformer(null, 2); 127 | 128 | // năm mươi sáu đô chín mươi xen, thay vì năm mươi sáu đô chín xen 129 | $transformer->toCurrency(56.90); 130 | ``` 131 | 132 | Ngoài ra ta còn có thể sử dụng đơn vị tiền tệ khác thông qua tham trị thứ 2 của phương thức 133 | `toCurrency`, với mảng phần từ đầu tiên là đơn vị cho số nguyên và kế tiếp là đơn vị của phân số: 134 | 135 | ```php 136 | 137 | use PHPViet\NumberToWords\Transformer; 138 | 139 | $transformer = new Transformer(); 140 | 141 | // sáu nghìn bảy trăm bốn mươi hai đô bảy xen 142 | $transformer->toCurrency(6742.7, ['đô', 'xen']); 143 | 144 | // chín nghìn bốn trăm chín mươi hai đô mười lăm xen 145 | $transformer->toCurrency(9492.15, ['đô', 'xen']); 146 | 147 | // tám nghìn ba trăm sáu mươi mốt đô bốn xen 148 | $transformer->toCurrency('8361.40', ['đô', 'xen']); 149 | ``` 150 | 151 | ### Thay cách đọc số 152 | 153 | Trong thư viện ngoài cách đọc tiêu chuẩn còn hổ trợ cho chúng ta lớp `PHPViet\NumberToWords\SouthDictionary` 154 | giúp đọc số theo phong cách trong Nam: 155 | 156 | ```php 157 | 158 | use PHPViet\NumberToWords\Transformer; 159 | use PHPViet\NumberToWords\SouthDictionary; 160 | 161 | $transformer = new Transformer(); 162 | $southDictionary = new SouthDictionary(); 163 | $southTransformer = new Transformer($southDictionary); 164 | 165 | $transformer->toWords(101); // một trăm linh một 166 | $southTransformer->toWords(101); // một trăm lẻ một 167 | 168 | $transformer->toWords(1000); // một nghìn 169 | $southTransformer->toWords(1000); // một ngàn 170 | 171 | $transformer->toWords(24) // hai mươi tư 172 | $southTransformer->toWords(24); // hai mươi bốn 173 | 174 | $transformer->toCurrency(124001); // một trăm hai mươi tư nghìn không trăm linh một 175 | $southTransformer->toCurrency(124001); // một trăm hai mươi bốn ngàn không trăm lẻ một 176 | ``` 177 | 178 | Nếu như bạn muốn thay đổi cách đọc theo ý bạn thì hãy tạo một lớp `Dictionary` kế thừa 179 | `PHPViet\NumberToWords\Dictionary` hoặc thực thi mẫu trừu tượng `PHPViet\NumberToWords\DictionaryInterface`: 180 | 181 | ```php 182 | 183 | use PHPViet\NumberToWords\Dictionary; 184 | use PHPViet\NumberToWords\Transformer; 185 | 186 | class MyDictionary extends Dictionary { 187 | 188 | /** 189 | * @inheritDoc 190 | */ 191 | public function specialTripletUnitFive(): string 192 | { 193 | return 'nhăm'; 194 | } 195 | 196 | } 197 | 198 | $transformer = new Transformer(); 199 | $myDictionary = new MyDictionary(); 200 | $myTransformer = new Transformer($myDictionary); 201 | 202 | $transformer->toWords(15); // mười lăm 203 | $myTransformer->toWords(15); // mười nhăm 204 | 205 | ``` 206 | 207 | ## Dành cho nhà phát triển 208 | 209 | Nếu như bạn cảm thấy thư viện còn thiếu sót hoặc sai sót và bạn muốn đóng góp để phát triển chung, 210 | chúng tôi rất hoan nghênh! Hãy tạo các `issue` để đóng góp ý tưởng cho phiên bản kế tiếp 211 | hoặc tạo `PR` để đóng góp. Cảm ơn! 212 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phpviet/number-to-words", 3 | "type": "library", 4 | "description": "Thư viện hổ trợ chuyển đổi số sang chữ số.", 5 | "keywords": [ 6 | "phpviet", 7 | "number-to-words" 8 | ], 9 | "homepage": "https://github.com/phpviet/number-to-words", 10 | "license": "MIT", 11 | "authors": [ 12 | { 13 | "name": "Vuong Xuong Minh", 14 | "email": "vuongxuongminh@gmail.com" 15 | } 16 | ], 17 | "require": { 18 | "php": ">=7.1" 19 | }, 20 | "require-dev": { 21 | "phpunit/phpunit": "~7.5", 22 | "scrutinizer/ocular": "^1.5" 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "PHPViet\\NumberToWords\\": "src" 27 | } 28 | }, 29 | "autoload-dev": { 30 | "psr-4": { 31 | "PHPViet\\NumberToWords\\Tests\\": "tests" 32 | } 33 | }, 34 | "scripts": { 35 | "test": "\"vendor/bin/phpunit\"" 36 | }, 37 | "config": { 38 | "sort-packages": true 39 | }, 40 | "extra": { 41 | "branch-alias": { 42 | "dev-master": "1.0-dev" 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Concerns/Collapse.php: -------------------------------------------------------------------------------- 1 | 13 | * 14 | * @since 1.2.0 15 | */ 16 | trait Collapse 17 | { 18 | /** 19 | * Ghép mảng chữ số thành chuỗi. 20 | * 21 | * @param array|string[] $words 22 | * @return string 23 | * 24 | * @since 1.2.0 25 | */ 26 | protected function collapseWords(array $words): string 27 | { 28 | $separator = $this->dictionary->separator(); 29 | $words = array_filter($words); 30 | 31 | return implode($separator, $words); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Concerns/NumberResolver.php: -------------------------------------------------------------------------------- 1 | 15 | * 16 | * @since 1.0.5 17 | */ 18 | trait NumberResolver 19 | { 20 | /** 21 | * Chia số truyền vào thành mảng bao gồm kiểu số âm hoặc dương, số nguyên và phân số. 22 | * 23 | * @param int|float|string $number 24 | * @return array 25 | * 26 | * @throws InvalidArgumentException 27 | */ 28 | protected function resolveNumber($number): array 29 | { 30 | if (! is_numeric($number)) { 31 | throw new InvalidArgumentException(sprintf('Number arg (`%s`) must be numeric!', $number)); 32 | } 33 | 34 | if ($this->decimalPart === null) { 35 | $number += 0; // trick xóa các số 0 lẻ sau cùng của phân số đối với input là chuỗi. 36 | $number = (string) $number; 37 | } else { 38 | $number = number_format($number, $this->decimalPart, '.', ''); 39 | } 40 | $minus = '-' === $number[0]; 41 | 42 | if (false !== strpos($number, '.')) { 43 | $numbers = explode('.', $number, 2); 44 | } else { 45 | $numbers = [$number, 0]; 46 | } 47 | 48 | return array_merge([$minus], array_map('abs', $numbers)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Concerns/TripletTransformer.php: -------------------------------------------------------------------------------- 1 | 13 | * 14 | * @since 1.0.0 15 | */ 16 | trait TripletTransformer 17 | { 18 | /** 19 | * Chuyển đổi cụm 3 số thành chữ số. 20 | * 21 | * @param int $triplet 22 | * @param bool $isFirst 23 | * @param int $exponent 24 | * @return string 25 | */ 26 | protected function tripletToWords(int $triplet, bool $isFirst, int $exponent): string 27 | { 28 | [$hundred, $ten, $unit] = $this->splitTriplet($triplet); 29 | 30 | if (0 < $hundred || ! $isFirst) { 31 | $words[] = $this->dictionary->getTripletHundred($hundred); 32 | 33 | if (0 === $ten && 0 < $unit) { 34 | $words[] = $this->dictionary->tripletTenSeparator(); 35 | } 36 | } 37 | 38 | if (0 < $ten) { 39 | $words[] = $this->dictionary->getTripletTen($ten); 40 | } 41 | 42 | if (0 < $unit) { 43 | $words[] = $this->getTripletUnit($unit, $ten); 44 | } 45 | 46 | $words[] = $this->dictionary->getExponent($exponent); 47 | 48 | return $this->collapseWords($words); 49 | } 50 | 51 | /** 52 | * Chia 3 số thành mảng 3 phần tử tương ứng với hàng trăm, hàng chục, hàng đơn vị. 53 | * 54 | * @param int $triplet 55 | * @return array 56 | */ 57 | private function splitTriplet(int $triplet): array 58 | { 59 | $hundred = (int) ($triplet / 100) % 10; 60 | $ten = (int) ($triplet / 10) % 10; 61 | $unit = $triplet % 10; 62 | 63 | return [$hundred, $ten, $unit]; 64 | } 65 | 66 | /** 67 | * Chuyển đổi số hàng đơn vị sang chữ số ở một số trường hợp đặc biệt. 68 | * 69 | * @param int $unit 70 | * @param int $ten 71 | * @return null|string 72 | */ 73 | private function getTripletUnit(int $unit, int $ten): string 74 | { 75 | if (1 <= $ten && 5 === $unit) { 76 | return $this->dictionary->specialTripletUnitFive(); 77 | } 78 | 79 | if (2 <= $ten) { 80 | if (1 === $unit) { 81 | return $this->dictionary->specialTripletUnitOne(); 82 | } 83 | 84 | if (4 === $unit) { 85 | return $this->dictionary->specialTripletUnitFour(); 86 | } 87 | } 88 | 89 | return $this->dictionary->getTripletUnit($unit); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/Concerns/TripletsConverter.php: -------------------------------------------------------------------------------- 1 | 13 | * 14 | * @since 1.0.0 15 | */ 16 | trait TripletsConverter 17 | { 18 | /** 19 | * Chia số truyền vào thành các cụm gồm 3 số để hổ trợ cho việc chuyển sang chữ số. 20 | * 21 | * @param int $number 22 | * @return array|int[] 23 | */ 24 | protected function numberToTriplets(int $number): array 25 | { 26 | $triplets = []; 27 | 28 | while (0 < $number) { 29 | array_unshift($triplets, $number % 1000); 30 | $number = (int) ($number / 1000); 31 | } 32 | 33 | return $triplets; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Dictionary.php: -------------------------------------------------------------------------------- 1 | 15 | * 16 | * @since 1.0.0 17 | */ 18 | class Dictionary implements DictionaryInterface 19 | { 20 | /** 21 | * Mảng tập hợp hàng đơn vị. 22 | * 23 | * @var array 24 | */ 25 | protected static $tripletUnits = [ 26 | 'không', 27 | 'một', 28 | 'hai', 29 | 'ba', 30 | 'bốn', 31 | 'năm', 32 | 'sáu', 33 | 'bảy', 34 | 'tám', 35 | 'chín', 36 | ]; 37 | 38 | /** 39 | * Mảng tập hợp hàng chục. 40 | * 41 | * @var array 42 | */ 43 | protected static $tripletTens = [ 44 | '', 45 | 'mười', 46 | 'hai mươi', 47 | 'ba mươi', 48 | 'bốn mươi', 49 | 'năm mươi', 50 | 'sáu mươi', 51 | 'bảy mươi', 52 | 'tám mươi', 53 | 'chín mươi', 54 | ]; 55 | 56 | /** 57 | * Từ ngữ mô tả hàng trăm. 58 | * 59 | * @var string 60 | */ 61 | protected static $hundred = 'trăm'; 62 | 63 | /** 64 | * Mảng tập hợp đơn vị tính dựa trên số mũ 3. 65 | * 66 | * @var array 67 | */ 68 | protected static $exponents = [ 69 | '', 70 | 'nghìn', 71 | 'triệu', 72 | 'tỷ', 73 | 'nghìn tỷ', 74 | 'triệu tỷ', 75 | ]; 76 | 77 | /** 78 | * {@inheritdoc} 79 | */ 80 | public function zero(): string 81 | { 82 | return static::$tripletUnits[0]; 83 | } 84 | 85 | /** 86 | * {@inheritdoc} 87 | */ 88 | public function minus(): string 89 | { 90 | return 'âm'; 91 | } 92 | 93 | /** 94 | * {@inheritdoc} 95 | */ 96 | public function separator(): string 97 | { 98 | return ' '; 99 | } 100 | 101 | /** 102 | * {@inheritdoc} 103 | */ 104 | public function tripletTenSeparator(): string 105 | { 106 | return 'linh'; 107 | } 108 | 109 | /** 110 | * {@inheritdoc} 111 | */ 112 | public function specialTripletUnitOne(): string 113 | { 114 | return 'mốt'; 115 | } 116 | 117 | /** 118 | * {@inheritdoc} 119 | */ 120 | public function specialTripletUnitFour(): string 121 | { 122 | return 'tư'; 123 | } 124 | 125 | /** 126 | * {@inheritdoc} 127 | */ 128 | public function specialTripletUnitFive(): string 129 | { 130 | return 'lăm'; 131 | } 132 | 133 | /** 134 | * {@inheritdoc} 135 | */ 136 | public function fraction(): string 137 | { 138 | return 'phẩy'; 139 | } 140 | 141 | /** 142 | * {@inheritdoc} 143 | */ 144 | public function getTripletUnit(int $unit): string 145 | { 146 | if (! isset(static::$tripletUnits[$unit])) { 147 | throw new InvalidArgumentException(sprintf('Unit arg (`%s`) must be in 0-9 range!', $unit)); 148 | } 149 | 150 | return static::$tripletUnits[$unit]; 151 | } 152 | 153 | /** 154 | * {@inheritdoc} 155 | */ 156 | public function getTripletTen(int $ten): string 157 | { 158 | if (! isset(static::$tripletTens[$ten])) { 159 | throw new InvalidArgumentException(sprintf('Ten arg (`%s`) must be in 0-9 range!', $ten)); 160 | } 161 | 162 | return static::$tripletTens[$ten]; 163 | } 164 | 165 | /** 166 | * {@inheritdoc} 167 | */ 168 | public function getTripletHundred(int $hundred): string 169 | { 170 | if (! isset(static::$tripletUnits[$hundred])) { 171 | throw new InvalidArgumentException(sprintf('Hundred arg (`%s`) must be in 0-9 range!', $hundred)); 172 | } 173 | 174 | return static::$tripletUnits[$hundred].$this->separator().static::$hundred; 175 | } 176 | 177 | /** 178 | * {@inheritdoc} 179 | */ 180 | public function getExponent(int $power): string 181 | { 182 | if (! isset(static::$exponents[$power])) { 183 | throw new InvalidArgumentException(sprintf('Power arg (`%s`) not exist in vietnamese dictionary!', $power)); 184 | } 185 | 186 | return static::$exponents[$power]; 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /src/DictionaryInterface.php: -------------------------------------------------------------------------------- 1 | 13 | * 14 | * @since 1.0.0 15 | */ 16 | interface DictionaryInterface 17 | { 18 | /** 19 | * Trả về từ ngữ diễn giải số 0. 20 | * 21 | * @return string 22 | */ 23 | public function zero(): string; 24 | 25 | /** 26 | * Trả về từ ngữ diễn giải số âm. 27 | * 28 | * @return string 29 | */ 30 | public function minus(): string; 31 | 32 | /** 33 | * Trả về giá trị ngắt các chữ số. 34 | * 35 | * @return string 36 | */ 37 | public function separator(): string; 38 | 39 | /** 40 | * Trả về từ ngữ ngắt giữa nguyên số và phân số. 41 | * 42 | * @return string 43 | */ 44 | public function fraction(): string; 45 | 46 | /** 47 | * Trả về từ ngữ khi chuyển đổi 1 sang chữ số khi chữ số hàng chục lớn hơn 1. 48 | * 49 | * @return string 50 | */ 51 | public function specialTripletUnitOne(): string; 52 | 53 | /** 54 | * Trả về từ ngữ khi chuyển đổi 4 sang chữ số khi chữ số hàng chục lớn hơn hoặc bằng 2. 55 | * 56 | * @return string 57 | */ 58 | public function specialTripletUnitFour(): string; 59 | 60 | /** 61 | * Trả về từ ngữ khi chuyển đổi 5 sang chữ số khi chữ số hàng chục lớn hơn hoặc bằng 1. 62 | * 63 | * @return string 64 | */ 65 | public function specialTripletUnitFive(): string; 66 | 67 | /** 68 | * Trả về từ ngữ nằm giữa hàng trăm và hàng đơn vị khi chữ số hàng chục là 0 và chữ số hàng trăm, đơn vị khác 0. 69 | * 70 | * @return string 71 | */ 72 | public function tripletTenSeparator(): string; 73 | 74 | /** 75 | * Trả về từ ngữ hàng đơn vị tương ứng với số truyền vào. 76 | * 77 | * @param int $unit hàng đơn vị 78 | * @return string 79 | */ 80 | public function getTripletUnit(int $unit): string; 81 | 82 | /** 83 | * Trả về từ ngữ hàng chục tương ứng với số truyền vào. 84 | * 85 | * @param int $ten hàng chục 86 | * @return string 87 | */ 88 | public function getTripletTen(int $ten): string; 89 | 90 | /** 91 | * Trả về từ ngữ hàng trăm tương ứng với số truyền vào. 92 | * 93 | * @param int $hundred hàng trăm 94 | * @return string 95 | */ 96 | public function getTripletHundred(int $hundred): string; 97 | 98 | /** 99 | * Trả về đơn vị tương ứng với số mũ cơ số 3. 100 | * 101 | * @param int $power hàng trăm 102 | * @return string 103 | */ 104 | public function getExponent(int $power): string; 105 | } 106 | -------------------------------------------------------------------------------- /src/SouthDictionary.php: -------------------------------------------------------------------------------- 1 | 13 | * 14 | * @since 1.0.0 15 | */ 16 | class SouthDictionary extends Dictionary 17 | { 18 | /** 19 | * Thay nghìn => ngàn. 20 | * 21 | * @var array 22 | */ 23 | protected static $exponents = [ 24 | '', 25 | 'ngàn', 26 | 'triệu', 27 | 'tỷ', 28 | 'ngàn tỷ', 29 | 'triệu tỷ', 30 | ]; 31 | 32 | /** 33 | * {@inheritdoc} 34 | */ 35 | public function tripletTenSeparator(): string 36 | { 37 | return 'lẻ'; 38 | } 39 | 40 | /** 41 | * {@inheritdoc} 42 | */ 43 | public function specialTripletUnitFour(): string 44 | { 45 | return 'bốn'; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Transformer.php: -------------------------------------------------------------------------------- 1 | 13 | * 14 | * @since 1.0.0 15 | */ 16 | class Transformer 17 | { 18 | use Concerns\Collapse; 19 | use Concerns\NumberResolver; 20 | use Concerns\TripletsConverter; 21 | use Concerns\TripletTransformer; 22 | 23 | /** 24 | * @var DictionaryInterface 25 | */ 26 | protected $dictionary; 27 | 28 | /** 29 | * Mặc định bỏ số các số 0 sau phần thập phân. 30 | * 31 | * @var int 32 | */ 33 | protected $decimalPart; 34 | 35 | /** 36 | * Tạo đối tượng mới với từ điển chỉ định và phần thập phân. 37 | * 38 | * @param DictionaryInterface $dictionary 39 | */ 40 | public function __construct(?DictionaryInterface $dictionary = null, $decimalPart = null) 41 | { 42 | if (null === $dictionary) { 43 | $dictionary = new Dictionary(); 44 | } 45 | 46 | $this->dictionary = $dictionary; 47 | $this->decimalPart = $decimalPart; 48 | } 49 | 50 | /** 51 | * Chuyển đổi số sang chữ số. 52 | * 53 | * @param int|float|string $number 54 | * @return string 55 | * 56 | * @throws \InvalidArgumentException 57 | */ 58 | public function toWords($number): string 59 | { 60 | [$minus, $number, $decimal] = $this->resolveNumber($number); 61 | $words[] = $minus ? $this->dictionary->minus() : ''; 62 | 63 | if (0 === $number) { 64 | $words[] = $this->dictionary->zero(); 65 | } 66 | 67 | $triplets = $this->numberToTriplets($number); 68 | 69 | foreach ($triplets as $pos => $triplet) { 70 | if (0 < $triplet) { 71 | $words[] = $this->tripletToWords($triplet, 0 === $pos, count($triplets) - $pos - 1); 72 | } 73 | } 74 | 75 | if (0 < $decimal) { 76 | $words[] = $this->dictionary->fraction(); 77 | $words[] = $this->toWords($decimal); 78 | } 79 | 80 | return $this->collapseWords($words); 81 | } 82 | 83 | /** 84 | * Chuyển đổi số sang chữ số kết hợp với đơn vị tiền tệ. 85 | * 86 | * @param $number 87 | * @param array|string[]|string $unit 88 | * @return string 89 | * 90 | * @throws \InvalidArgumentException 91 | */ 92 | public function toCurrency($number, $unit = 'đồng'): string 93 | { 94 | $unit = (array) $unit; 95 | $originNumber = $number; 96 | [$minus, $number, $decimal] = $this->resolveNumber($number); 97 | 98 | if (0 === $decimal || ! isset($unit[1])) { 99 | $words[] = $this->toWords($originNumber); 100 | $words[] = $unit[0]; 101 | } else { 102 | [$unit, $decimalUnit] = $unit; 103 | $words[] = $minus ? $this->dictionary->minus() : ''; 104 | $words[] = $this->toWords($number); 105 | $words[] = $unit; 106 | $words[] = $this->toWords($decimal); 107 | $words[] = $decimalUnit; 108 | } 109 | 110 | return $this->collapseWords($words); 111 | } 112 | } 113 | --------------------------------------------------------------------------------