num2words 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +40 -0
- data/CHANGELOG.md +18 -0
- data/README.md +26 -0
- data/Rakefile +38 -2
- data/benchmark/converter_benchmark.rb +96 -0
- data/docs/api.md +422 -0
- data/docs/api.ru.md +422 -0
- data/docs/limits.md +140 -0
- data/docs/limits.ru.md +140 -0
- data/docs/locale_development.md +241 -0
- data/docs/locale_development.ru.md +241 -0
- data/lib/num2words/version.rb +1 -1
- data/num2words.gemspec +1 -0
- metadata +24 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 78f705a73f571176b4d920dfe220590d2bd217ea513fb817028a0ae2c22221cd
|
|
4
|
+
data.tar.gz: 1e8726b93feee82a3b87143ae8a25edf388d726f65ecf424ec713fcc4323ea08
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d8a078fef78bc1e26fc28d90c6604e6a3a09aa05e3b716df2faea6d7423bb91a4de1c907eaa7d7e9c85b0d3019fa98257f6b499113f1987d646c902680bcdd66
|
|
7
|
+
data.tar.gz: a87e663b01668bdf114cba5eb2c2f9f55b453b4aae314b5ceceac78047574e1fc5917a46d97fddaf60cea2a64333c2b1f0901694daed5aade3beff7d6682c1b9
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
- master
|
|
8
|
+
pull_request:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
name: Ruby ${{ matrix.ruby }}
|
|
13
|
+
runs-on: ubuntu-22.04
|
|
14
|
+
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
ruby:
|
|
19
|
+
- "2.7"
|
|
20
|
+
- "3.0"
|
|
21
|
+
- "3.1"
|
|
22
|
+
- "3.2"
|
|
23
|
+
- "3.3"
|
|
24
|
+
- "3.4"
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- name: Checkout
|
|
28
|
+
uses: actions/checkout@v4
|
|
29
|
+
|
|
30
|
+
- name: Set up Ruby
|
|
31
|
+
uses: ruby/setup-ruby@v1
|
|
32
|
+
with:
|
|
33
|
+
ruby-version: ${{ matrix.ruby }}
|
|
34
|
+
bundler-cache: true
|
|
35
|
+
|
|
36
|
+
- name: Run specs
|
|
37
|
+
run: bundle exec rspec
|
|
38
|
+
|
|
39
|
+
- name: Build gem
|
|
40
|
+
run: gem build num2words.gemspec
|
data/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,24 @@
|
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
+
## [0.3.1] - 2026-07-04
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- Набор benchmark-проверок: `benchmark/converter_benchmark.rb` и `bundle exec rake benchmark`.
|
|
18
|
+
- Справочник API: `docs/api.md` и `docs/api.ru.md`.
|
|
19
|
+
- Документация по числовым лимитам: `docs/limits.md` и `docs/limits.ru.md`.
|
|
20
|
+
- Rake-задачи для разработки и релизной проверки:
|
|
21
|
+
- `bundle exec rake spec`
|
|
22
|
+
- `bundle exec rake build`
|
|
23
|
+
- `bundle exec rake release:check`
|
|
24
|
+
- `bundle exec rake locales`
|
|
25
|
+
- `bundle exec rake currencies`
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
- Добавлена runtime-зависимость `bigdecimal` для совместимости с Ruby 3.4+.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
14
32
|
## [0.3.0] - 2026-06-27
|
|
15
33
|
|
|
16
34
|
### Added
|
data/README.md
CHANGED
|
@@ -143,6 +143,16 @@ Num2words.to_currency(BigDecimal("21.05"), :ru)
|
|
|
143
143
|
- `minor: :always | :nonzero | :never` — вывод младшей денежной единицы.
|
|
144
144
|
- `code: :USD` — выбор валюты для `to_currency`.
|
|
145
145
|
|
|
146
|
+
Полная справка по API:
|
|
147
|
+
|
|
148
|
+
- [English](docs/api.md)
|
|
149
|
+
- [Русский](docs/api.ru.md)
|
|
150
|
+
|
|
151
|
+
Ограничения числовых разрядов:
|
|
152
|
+
|
|
153
|
+
- [English](docs/limits.md)
|
|
154
|
+
- [Русский](docs/limits.ru.md)
|
|
155
|
+
|
|
146
156
|
---
|
|
147
157
|
|
|
148
158
|
## Консоль
|
|
@@ -203,6 +213,11 @@ KZT MYR NOK PKR PLN RON RSD RUB SAR SEK THB TRY UAH USD VND
|
|
|
203
213
|
|
|
204
214
|
После добавления локали стоит покрыть ее отдельным spec и добавить в `spec/currency_catalog_spec.rb`.
|
|
205
215
|
|
|
216
|
+
Подробная инструкция:
|
|
217
|
+
|
|
218
|
+
- [English](docs/locale_development.md)
|
|
219
|
+
- [Русский](docs/locale_development.ru.md)
|
|
220
|
+
|
|
206
221
|
---
|
|
207
222
|
|
|
208
223
|
## Тестирование
|
|
@@ -211,6 +226,17 @@ KZT MYR NOK PKR PLN RON RSD RUB SAR SEK THB TRY UAH USD VND
|
|
|
211
226
|
bundle exec rspec
|
|
212
227
|
```
|
|
213
228
|
|
|
229
|
+
## Rake tasks
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
bundle exec rake spec
|
|
233
|
+
bundle exec rake build
|
|
234
|
+
bundle exec rake release:check
|
|
235
|
+
bundle exec rake locales
|
|
236
|
+
bundle exec rake currencies
|
|
237
|
+
bundle exec rake benchmark
|
|
238
|
+
```
|
|
239
|
+
|
|
214
240
|
---
|
|
215
241
|
|
|
216
242
|
## Roadmap
|
data/Rakefile
CHANGED
|
@@ -2,9 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
require "bundler/gem_tasks"
|
|
4
4
|
require "rspec/core/rake_task"
|
|
5
|
+
require "yaml"
|
|
5
6
|
|
|
6
|
-
# таска для запуска тестов
|
|
7
7
|
RSpec::Core::RakeTask.new(:spec)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
task build: "build:clean"
|
|
10
|
+
|
|
11
|
+
namespace :build do
|
|
12
|
+
task :clean do
|
|
13
|
+
Dir.glob("num2words-*.gem").each { |file| File.delete(file) }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
namespace :release do
|
|
18
|
+
desc "Run tests and build the gem"
|
|
19
|
+
task check: [:spec, :build]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
desc "Print supported locale codes"
|
|
23
|
+
task :locales do
|
|
24
|
+
locales = Dir[File.expand_path("config/locales/*.yml", __dir__)]
|
|
25
|
+
.map { |file| File.basename(file, ".yml") }
|
|
26
|
+
.sort
|
|
27
|
+
|
|
28
|
+
puts locales.join(" ")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
desc "Print supported currency codes"
|
|
32
|
+
task :currencies do
|
|
33
|
+
currencies = YAML.load_file(File.expand_path("config/locales/ru.yml", __dir__))
|
|
34
|
+
.dig("ru", "num2words", "currencies")
|
|
35
|
+
.keys
|
|
36
|
+
.sort
|
|
37
|
+
|
|
38
|
+
puts currencies.join(" ")
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
desc "Run converter benchmark"
|
|
42
|
+
task :benchmark do
|
|
43
|
+
sh "ruby benchmark/converter_benchmark.rb"
|
|
44
|
+
end
|
|
45
|
+
|
|
10
46
|
task default: :spec
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "benchmark"
|
|
4
|
+
require_relative "../lib/num2words"
|
|
5
|
+
|
|
6
|
+
DEFAULT_ITERATIONS = 100
|
|
7
|
+
|
|
8
|
+
def all_locales
|
|
9
|
+
Dir[File.expand_path("../config/locales/*.yml", __dir__)]
|
|
10
|
+
.map { |file| File.basename(file, ".yml").to_sym }
|
|
11
|
+
.sort
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def selected_locales
|
|
15
|
+
requested = ENV.fetch("LOCALES", "").split(",").map(&:strip).reject(&:empty?).map(&:to_sym)
|
|
16
|
+
return all_locales if requested.empty?
|
|
17
|
+
|
|
18
|
+
unknown = requested - all_locales
|
|
19
|
+
abort "Unknown locales: #{unknown.join(', ')}" unless unknown.empty?
|
|
20
|
+
|
|
21
|
+
requested
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def iterations
|
|
25
|
+
Integer(ENV.fetch("ITERATIONS", DEFAULT_ITERATIONS.to_s))
|
|
26
|
+
rescue ArgumentError
|
|
27
|
+
abort "ITERATIONS must be an integer"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
SCENARIOS = {
|
|
31
|
+
integer: ->(locale) { Num2words.to_words(123_456_789, locale) },
|
|
32
|
+
decimal: ->(locale) { Num2words.to_words("12345.67", locale) },
|
|
33
|
+
date: ->(locale) { Num2words.to_words("2024-08-21", locale) },
|
|
34
|
+
time: ->(locale) { Num2words.to_words("14:35:42", locale) },
|
|
35
|
+
datetime: ->(locale) { Num2words.to_words("2024-08-21 14:35:42", locale) },
|
|
36
|
+
currency: ->(locale) { Num2words.to_currency("12345.67", locale) }
|
|
37
|
+
}.freeze
|
|
38
|
+
|
|
39
|
+
def measure_scenarios(locales, iterations_count)
|
|
40
|
+
SCENARIOS.map do |name, callable|
|
|
41
|
+
calls = locales.size * iterations_count
|
|
42
|
+
elapsed = Benchmark.realtime do
|
|
43
|
+
iterations_count.times do
|
|
44
|
+
locales.each { |locale| callable.call(locale) }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
[name, calls, elapsed]
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def measure_slowest_locales(locales, iterations_count)
|
|
53
|
+
locales.map do |locale|
|
|
54
|
+
calls = SCENARIOS.size * iterations_count
|
|
55
|
+
elapsed = Benchmark.realtime do
|
|
56
|
+
iterations_count.times do
|
|
57
|
+
SCENARIOS.each_value { |callable| callable.call(locale) }
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
[locale, calls, elapsed]
|
|
62
|
+
end.sort_by { |(_, _, elapsed)| -elapsed }.first(10)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def print_table(headers, rows)
|
|
66
|
+
widths = headers.each_with_index.map do |header, index|
|
|
67
|
+
([header.length] + rows.map { |row| row[index].to_s.length }).max
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
puts headers.each_with_index.map { |header, index| header.ljust(widths[index]) }.join(" ")
|
|
71
|
+
puts widths.map { |width| "-" * width }.join(" ")
|
|
72
|
+
rows.each do |row|
|
|
73
|
+
puts row.each_with_index.map { |value, index| value.to_s.ljust(widths[index]) }.join(" ")
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
locales = selected_locales
|
|
78
|
+
iterations_count = iterations
|
|
79
|
+
|
|
80
|
+
puts "num2words benchmark"
|
|
81
|
+
puts "Locales: #{locales.join(', ')}"
|
|
82
|
+
puts "Iterations per locale: #{iterations_count}"
|
|
83
|
+
puts
|
|
84
|
+
|
|
85
|
+
scenario_rows = measure_scenarios(locales, iterations_count).map do |name, calls, elapsed|
|
|
86
|
+
[name, calls, format("%.4f", elapsed), format("%.4f", (elapsed / calls) * 1000)]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
print_table(["Scenario", "Calls", "Total, s", "ms/call"], scenario_rows)
|
|
90
|
+
puts
|
|
91
|
+
|
|
92
|
+
slowest_rows = measure_slowest_locales(locales, iterations_count).map do |locale, calls, elapsed|
|
|
93
|
+
[locale, calls, format("%.4f", elapsed), format("%.4f", (elapsed / calls) * 1000)]
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
print_table(["Slowest locale", "Calls", "Total, s", "ms/call"], slowest_rows)
|
data/docs/api.md
ADDED
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
This document describes the public API of `num2words`.
|
|
4
|
+
|
|
5
|
+
## Loading
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
require "num2words"
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This loads the module API and core extensions for supported Ruby classes.
|
|
12
|
+
|
|
13
|
+
## Module API
|
|
14
|
+
|
|
15
|
+
### `Num2words.to_words`
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
Num2words.to_words(value, locale = I18n.default_locale, only = nil, short = false, **options)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Converts numbers, dates, times and date-times to words.
|
|
22
|
+
|
|
23
|
+
Examples:
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
Num2words.to_words(123, :ru)
|
|
27
|
+
# => "сто двадцать три"
|
|
28
|
+
|
|
29
|
+
Num2words.to_words("3,5", :ru)
|
|
30
|
+
# => "три целых пять десятых"
|
|
31
|
+
|
|
32
|
+
Num2words.to_words("2024-08-21", :en)
|
|
33
|
+
# => "the twenty-first of August, two thousand twenty four"
|
|
34
|
+
|
|
35
|
+
Num2words.to_words("14:35:42", :fr)
|
|
36
|
+
# => "quatorze heures trente cinq minutes quarante deux secondes"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Keyword locale form is also supported:
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
Num2words.to_words(123, locale: :en)
|
|
43
|
+
# => "one hundred twenty three"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### `Num2words.to_currency`
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
Num2words.to_currency(amount, locale = I18n.default_locale, **options)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Converts a numeric amount to words using the selected locale and currency.
|
|
53
|
+
|
|
54
|
+
Examples:
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
Num2words.to_currency("21,05", :ru)
|
|
58
|
+
# => "двадцать один рубль пять копеек"
|
|
59
|
+
|
|
60
|
+
Num2words.to_currency(12.50, :en, code: :EUR)
|
|
61
|
+
# => "twelve euros fifty cents"
|
|
62
|
+
|
|
63
|
+
Num2words.to_currency(BigDecimal("21.05"), :ru)
|
|
64
|
+
# => "двадцать один рубль пять копеек"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Core Extensions
|
|
68
|
+
|
|
69
|
+
`num2words` adds convenience methods to common classes.
|
|
70
|
+
|
|
71
|
+
### `Integer#to_words`
|
|
72
|
+
|
|
73
|
+
```ruby
|
|
74
|
+
123.to_words(:ru)
|
|
75
|
+
# => "сто двадцать три"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### `Integer#to_currency`
|
|
79
|
+
|
|
80
|
+
```ruby
|
|
81
|
+
123.to_currency(:en, code: :USD)
|
|
82
|
+
# => "one hundred twenty three dollars zero cents"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### `Float#to_words`
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
45.67.to_words(:ru)
|
|
89
|
+
# => "сорок пять целых шестьдесят семь сотых"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### `Float#to_currency`
|
|
93
|
+
|
|
94
|
+
```ruby
|
|
95
|
+
12.5.to_currency(:ru, code: :USD)
|
|
96
|
+
# => "двенадцать долларов пятьдесят центов"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### `String#to_words`
|
|
100
|
+
|
|
101
|
+
```ruby
|
|
102
|
+
"007".to_words(:en)
|
|
103
|
+
# => "seven"
|
|
104
|
+
|
|
105
|
+
"3,5".to_words(:ru)
|
|
106
|
+
# => "три целых пять десятых"
|
|
107
|
+
|
|
108
|
+
"2024-08-21 14:35:42".to_words(:ru)
|
|
109
|
+
# => "двадцать первое августа две тысячи двадцать четвёртого года, четырнадцать часов тридцать пять минут сорок две секунды"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`String#to_currency` is not currently defined. Use `Num2words.to_currency("12.50", :en)` for string amounts.
|
|
113
|
+
|
|
114
|
+
### `Date#to_words`
|
|
115
|
+
|
|
116
|
+
```ruby
|
|
117
|
+
Date.new(2024, 8, 21).to_words(:ru)
|
|
118
|
+
# => "двадцать первое августа две тысячи двадцать четвёртого года"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### `Time#to_words`
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
Time.new(2024, 8, 21, 14, 35, 42).to_words(:en)
|
|
125
|
+
# => "fourteen hours thirty five minutes forty two seconds"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### `DateTime#to_words`
|
|
129
|
+
|
|
130
|
+
```ruby
|
|
131
|
+
DateTime.parse("2024-08-21 14:35:42").to_words(:en)
|
|
132
|
+
# => "the twenty-first of August, two thousand twenty four at fourteen hours thirty five minutes forty two seconds"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Supported Input Types
|
|
136
|
+
|
|
137
|
+
`to_words` supports:
|
|
138
|
+
|
|
139
|
+
- `Integer`
|
|
140
|
+
- `Float`
|
|
141
|
+
- `Date`
|
|
142
|
+
- `Time`
|
|
143
|
+
- `DateTime`
|
|
144
|
+
- integer strings, for example `"007"` or `"-42"`
|
|
145
|
+
- decimal strings with dot or comma, for example `"3.5"` or `"3,5"`
|
|
146
|
+
- date strings, for example `"2024-08-21"` or `"21.08.2024"`
|
|
147
|
+
- time strings, for example `"14:35"` or `"14:35:42"`
|
|
148
|
+
- date-time strings, for example `"2024-08-21 14:35:42"`
|
|
149
|
+
|
|
150
|
+
`to_currency` supports:
|
|
151
|
+
|
|
152
|
+
- `Integer`
|
|
153
|
+
- `Float`
|
|
154
|
+
- `String`
|
|
155
|
+
- `BigDecimal`
|
|
156
|
+
|
|
157
|
+
String currency amounts may use dot or comma as decimal separator.
|
|
158
|
+
|
|
159
|
+
## Options
|
|
160
|
+
|
|
161
|
+
### `locale`
|
|
162
|
+
|
|
163
|
+
Selects the locale.
|
|
164
|
+
|
|
165
|
+
```ruby
|
|
166
|
+
Num2words.to_words(123, :ru)
|
|
167
|
+
Num2words.to_words(123, locale: :ru)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
If no locale is passed, `I18n.default_locale` is used.
|
|
171
|
+
|
|
172
|
+
### `style`
|
|
173
|
+
|
|
174
|
+
Controls fractional output in `to_words`.
|
|
175
|
+
|
|
176
|
+
Supported values:
|
|
177
|
+
|
|
178
|
+
- `:fraction` - default fraction style.
|
|
179
|
+
- `:decimal` - reads fractional digits one by one when the locale supports decimal digit style.
|
|
180
|
+
|
|
181
|
+
```ruby
|
|
182
|
+
Num2words.to_words(12.12, :en)
|
|
183
|
+
# => "twelve and twelve hundredths"
|
|
184
|
+
|
|
185
|
+
Num2words.to_words(12.12, :en, style: :decimal)
|
|
186
|
+
# => "twelve point one two"
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### `joiner`
|
|
190
|
+
|
|
191
|
+
Controls the connector for fraction style.
|
|
192
|
+
|
|
193
|
+
Supported values:
|
|
194
|
+
|
|
195
|
+
- `:default`
|
|
196
|
+
- `:and`
|
|
197
|
+
|
|
198
|
+
```ruby
|
|
199
|
+
Num2words.to_words(0.5, :ru)
|
|
200
|
+
# => "ноль целых пять десятых"
|
|
201
|
+
|
|
202
|
+
Num2words.to_words(0.5, :ru, joiner: :and)
|
|
203
|
+
# => "ноль и пять десятых"
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Invalid values raise `ArgumentError`.
|
|
207
|
+
|
|
208
|
+
### `date_case`
|
|
209
|
+
|
|
210
|
+
Controls date day case for locales that support it.
|
|
211
|
+
|
|
212
|
+
Supported values:
|
|
213
|
+
|
|
214
|
+
- `:default`
|
|
215
|
+
- `:genitive`
|
|
216
|
+
|
|
217
|
+
```ruby
|
|
218
|
+
Num2words.to_words("2024-08-21", :ru)
|
|
219
|
+
# => "двадцать первое августа две тысячи двадцать четвёртого года"
|
|
220
|
+
|
|
221
|
+
Num2words.to_words("2024-08-21", :ru, date_case: :genitive)
|
|
222
|
+
# => "двадцать первого августа две тысячи двадцать четвёртого года"
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Invalid values raise `ArgumentError`.
|
|
226
|
+
|
|
227
|
+
### `short`
|
|
228
|
+
|
|
229
|
+
Enables short output for time or date-time values.
|
|
230
|
+
|
|
231
|
+
```ruby
|
|
232
|
+
Num2words.to_words("14:35:42", :ru, short: true)
|
|
233
|
+
# => "четырнадцать часов тридцать пять минут"
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
With date-time values, `short: true` returns a shortened date-time string unless `only` is used.
|
|
237
|
+
|
|
238
|
+
### `only`
|
|
239
|
+
|
|
240
|
+
Selects a part of a date-time value.
|
|
241
|
+
|
|
242
|
+
```ruby
|
|
243
|
+
Num2words.to_words("2024-08-21 14:35:42", :ru, only: :date)
|
|
244
|
+
# => "двадцать первое августа две тысячи двадцать четвёртого года"
|
|
245
|
+
|
|
246
|
+
Num2words.to_words("2024-08-21 14:35:42", :ru, only: :time)
|
|
247
|
+
# => "четырнадцать часов тридцать пять минут сорок две секунды"
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
The legacy positional form is also supported:
|
|
251
|
+
|
|
252
|
+
```ruby
|
|
253
|
+
"2024-08-21 14:35:42".to_words(:ru, :date)
|
|
254
|
+
"2024-08-21 14:35:42".to_words(:ru, :time)
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### `format`
|
|
258
|
+
|
|
259
|
+
Used by date and time conversion.
|
|
260
|
+
|
|
261
|
+
For dates:
|
|
262
|
+
|
|
263
|
+
- `:default`
|
|
264
|
+
- `:nominative` when provided by locale data.
|
|
265
|
+
- `:short` returns numeric date format `DD.MM.YYYY`.
|
|
266
|
+
|
|
267
|
+
For times:
|
|
268
|
+
|
|
269
|
+
- `:default`
|
|
270
|
+
- `:hours_only`
|
|
271
|
+
- `:hours_minutes`
|
|
272
|
+
- `:hours_minutes_seconds`
|
|
273
|
+
|
|
274
|
+
```ruby
|
|
275
|
+
Num2words.to_words("14:35:42", :ru, format: :hours_minutes)
|
|
276
|
+
# => "четырнадцать часов тридцать пять минут"
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Unsupported time formats raise `ArgumentError`.
|
|
280
|
+
|
|
281
|
+
### `word_case`
|
|
282
|
+
|
|
283
|
+
Changes result casing.
|
|
284
|
+
|
|
285
|
+
Supported values:
|
|
286
|
+
|
|
287
|
+
- `:default`
|
|
288
|
+
- `:upper`
|
|
289
|
+
- `:downcase`
|
|
290
|
+
- `:capitalize`
|
|
291
|
+
- `:title`
|
|
292
|
+
|
|
293
|
+
```ruby
|
|
294
|
+
Num2words.to_words(21, :en, word_case: :upper)
|
|
295
|
+
# => "TWENTY ONE"
|
|
296
|
+
|
|
297
|
+
Num2words.to_words(21, :en, word_case: :title)
|
|
298
|
+
# => "Twenty One"
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### `feminine`
|
|
302
|
+
|
|
303
|
+
For locales with grammatical gender, selects feminine forms where supported.
|
|
304
|
+
|
|
305
|
+
```ruby
|
|
306
|
+
Num2words.to_words(1, :ru, feminine: true)
|
|
307
|
+
# => "одна"
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### `code`
|
|
311
|
+
|
|
312
|
+
Selects currency code in `to_currency`.
|
|
313
|
+
|
|
314
|
+
```ruby
|
|
315
|
+
Num2words.to_currency(12.50, :ru, code: :USD)
|
|
316
|
+
# => "двенадцать долларов пятьдесят центов"
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
If the currency is not available for the locale, `num2words` falls back to the locale default currency and may emit a warning depending on configuration.
|
|
320
|
+
|
|
321
|
+
### `minor`
|
|
322
|
+
|
|
323
|
+
Controls minor currency unit output.
|
|
324
|
+
|
|
325
|
+
Supported values:
|
|
326
|
+
|
|
327
|
+
- `:always` - always include minor units.
|
|
328
|
+
- `:nonzero` - include minor units only when the minor value is greater than zero.
|
|
329
|
+
- `:never` - do not include minor units.
|
|
330
|
+
|
|
331
|
+
```ruby
|
|
332
|
+
Num2words.to_currency(12, :ru)
|
|
333
|
+
# => "двенадцать рублей ноль копеек"
|
|
334
|
+
|
|
335
|
+
Num2words.to_currency(12, :ru, minor: :nonzero)
|
|
336
|
+
# => "двенадцать рублей"
|
|
337
|
+
|
|
338
|
+
Num2words.to_currency(12.50, :ru, minor: :never)
|
|
339
|
+
# => "двенадцать рублей"
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Invalid values raise `ArgumentError`.
|
|
343
|
+
|
|
344
|
+
## Configuration
|
|
345
|
+
|
|
346
|
+
### `Num2words.default_currency`
|
|
347
|
+
|
|
348
|
+
Gets or sets default currency.
|
|
349
|
+
|
|
350
|
+
```ruby
|
|
351
|
+
Num2words.default_currency(:ru)
|
|
352
|
+
# => :RUB
|
|
353
|
+
|
|
354
|
+
Num2words.default_currency(:ru, :USD)
|
|
355
|
+
# => :USD
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### `Num2words.available_currencies`
|
|
359
|
+
|
|
360
|
+
Returns currency codes available for a locale.
|
|
361
|
+
|
|
362
|
+
```ruby
|
|
363
|
+
Num2words.available_currencies(:ru)
|
|
364
|
+
# => [:RUB, :USD, :EUR, ...]
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### `Num2words.currency_warnings`
|
|
368
|
+
|
|
369
|
+
Controls warnings when requested currency is unavailable.
|
|
370
|
+
|
|
371
|
+
```ruby
|
|
372
|
+
Num2words.currency_warnings = false
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
## Locales and Currencies
|
|
376
|
+
|
|
377
|
+
Supported locales:
|
|
378
|
+
|
|
379
|
+
```text
|
|
380
|
+
ar be bg bn cs da de el en es et fa fi fr gu he hi hr hu id it ja kn ko
|
|
381
|
+
kz lt lv ml mr ms nb nl pa pl pt ro ru sk sl sr sv sw ta te th tr uk ur
|
|
382
|
+
vi zh
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
Each completed locale supports the same 32 currency codes:
|
|
386
|
+
|
|
387
|
+
```text
|
|
388
|
+
BDT BGN BRL BYN CNY CZK DKK EUR GBP HUF IDR ILS INR IRR JPY KES KRW
|
|
389
|
+
KZT MYR NOK PKR PLN RON RSD RUB SAR SEK THB TRY UAH USD VND
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
## Errors
|
|
393
|
+
|
|
394
|
+
Unsupported input type:
|
|
395
|
+
|
|
396
|
+
```ruby
|
|
397
|
+
Num2words.to_words(Object.new, :en)
|
|
398
|
+
# raises ArgumentError: Unsupported input type: ...
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
Unsupported options:
|
|
402
|
+
|
|
403
|
+
```ruby
|
|
404
|
+
Num2words.to_words(0.5, :ru, joiner: :plus)
|
|
405
|
+
# raises ArgumentError: Unsupported joiner option: :plus
|
|
406
|
+
|
|
407
|
+
Num2words.to_currency(12, :ru, minor: :sometimes)
|
|
408
|
+
# raises ArgumentError: Unsupported minor option: :sometimes
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
Unsupported currency amount:
|
|
412
|
+
|
|
413
|
+
```ruby
|
|
414
|
+
Num2words.to_currency("abc", :en)
|
|
415
|
+
# raises ArgumentError: Unsupported currency amount: "abc"
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
## Development References
|
|
419
|
+
|
|
420
|
+
- [Numeric limits](limits.md)
|
|
421
|
+
- [Locale development guide](locale_development.md)
|
|
422
|
+
- [Russian locale development guide](locale_development.ru.md)
|