farsifu 0.4.1 → 0.5.0
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.
- data/README.md +21 -24
- data/farsifu.gemspec +2 -2
- data/lib/farsifu/constants.rb +8 -12
- data/lib/farsifu/num_to_word.rb +86 -50
- data/lib/farsifu/punch.rb +5 -9
- data/lib/farsifu/version.rb +1 -1
- data/spec/farsifu_spec.rb +8 -0
- metadata +4 -3
data/README.md
CHANGED
@@ -2,8 +2,9 @@
|
|
2
2
|
farsifu is a toolbox for developing ruby applications in Persian (Farsi) language.
|
3
3
|
|
4
4
|
## Features
|
5
|
-
* Converting numbers to Persian numbers
|
6
|
-
* Spelling numbers in Persian (
|
5
|
+
* Converting numbers to and from Persian numbers
|
6
|
+
* Spelling numbers in Persian (supports ordinal spelling of numbers in Persian)
|
7
|
+
* Converting Persian spelling of numbers back to normal numbers (see examples below)
|
7
8
|
* List of Iran's provinces, cities, counties
|
8
9
|
* List of countries in Persian
|
9
10
|
|
@@ -15,7 +16,10 @@ farsifu is a toolbox for developing ruby applications in Persian (Farsi) languag
|
|
15
16
|
-2567023.spell_farsi # => "منفی دو میلیون و پانصد و شصت و هفت هزار و بیست و سه"
|
16
17
|
7.53.spell_farsi # => "هفت ممیز پنجاه و سه صدم"
|
17
18
|
-0.999.spell_farsi # => "منفی صفر ممیز نهصد و نود و نه هزارم"
|
19
|
+
# Passing false to spell_farsi method will turn off the verbose mode.
|
20
|
+
-0.999.spell_farsi(false) # => "منفی نهصد و نود و نه هزارم"
|
18
21
|
12.spell_ordinal_farsi # => "دوازدهم"
|
22
|
+
# Note the different when you pass true to spell_ordinal_farsi method.
|
19
23
|
12.spell_ordinal_farsi(true) # => "دوازدهمین"
|
20
24
|
"هزار و چهل و پنج".farsi_to_number # => 1045
|
21
25
|
|
@@ -35,46 +39,39 @@ farsifu is a toolbox for developing ruby applications in Persian (Farsi) languag
|
|
35
39
|
gem install farsifu
|
36
40
|
|
37
41
|
## Changelog
|
42
|
+
### 0.5.0 - 15.FEB.2013
|
43
|
+
* [Arash Mousavi](https://github.com/arashm) is now a collaborator.
|
44
|
+
* Passing false to spell_farsi method will turn off the verbose mode.
|
45
|
+
* Major internal refactoring. Should not change the external API.
|
46
|
+
|
38
47
|
### 0.4.0 - 4.FEB.2013
|
39
|
-
*
|
48
|
+
* Added `farsi_to_number` to convert farsi spelling of numbers to real numbers , courtesy of [Arash Mousavi](https://github.com/arashm)
|
40
49
|
* Major refactoring and reorganization of the code, courtesy of [Arash Mousavi](https://github.com/arashm)
|
41
50
|
|
42
|
-
|
43
51
|
### 0.3.0 - 28.JAN.2013
|
44
|
-
*
|
45
|
-
|
52
|
+
* Added Farsi ordinal spelling, courtesy of [Arash Mousavi](https://github.com/arashm)
|
46
53
|
|
47
54
|
### 0.2.2 - 11.APR.2011
|
48
|
-
*
|
55
|
+
* Added ruby 1.9 compatibility, courtesy of Brian Kaney
|
49
56
|
|
50
57
|
### 0.2.1 - 11.JAN.2011
|
51
|
-
*
|
52
|
-
*
|
53
|
-
*
|
58
|
+
* Updated Readme
|
59
|
+
* Updated rspec to 2.4
|
60
|
+
* No longer replacing * with ×
|
54
61
|
|
55
62
|
### 0.2 - 2.MAR.2010
|
56
|
-
*
|
63
|
+
* Renamed gem from FarsiFu to farsifu
|
57
64
|
* Added a spec suite
|
58
65
|
* Migrated the gem to rubygems.org
|
59
66
|
* Added Iran Module
|
60
67
|
|
61
68
|
### 0.02 - 10.AUG.2008
|
62
|
-
*
|
63
|
-
* rdocs
|
69
|
+
* Converted into a gem
|
70
|
+
* Added rdocs documentation
|
64
71
|
|
65
72
|
### 0.01 - 07.AUG.2008
|
66
|
-
*
|
67
|
-
|
68
|
-
|
69
|
-
## Note on Patches/Pull Requests
|
73
|
+
* Initial release
|
70
74
|
|
71
|
-
* Fork the project.
|
72
|
-
* Make your feature addition or bug fix.
|
73
|
-
* Add tests for it. This is important so I don't break it in a
|
74
|
-
future version unintentionally.
|
75
|
-
* Commit, do not mess with rakefile, version, or history.
|
76
|
-
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
77
|
-
* Send me a pull request. Bonus points for topic branches.
|
78
75
|
|
79
76
|
## Copyright
|
80
77
|
|
data/farsifu.gemspec
CHANGED
@@ -6,8 +6,8 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.name = "farsifu"
|
7
7
|
s.version = FarsiFu::VERSION
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
|
-
s.authors = ["Allen A. Bargi"]
|
10
|
-
s.email = %q{allen.bargi@gmail.com}
|
9
|
+
s.authors = ["Allen A. Bargi", "Arash Mousavi"]
|
10
|
+
s.email = %q{allen.bargi@gmail.com mousavi.arash@gmail.com}
|
11
11
|
s.homepage = %q{http://github.com/aziz/farsifu}
|
12
12
|
s.summary = %q{a toolbox for developing ruby applications in Persian (Farsi) language, see readme file for features}
|
13
13
|
s.description = %q{a toolbox for developing ruby applications in Persian (Farsi) language, see readme file for features}
|
data/lib/farsifu/constants.rb
CHANGED
@@ -4,16 +4,9 @@ module FarsiFu
|
|
4
4
|
PERSIAN_CHARS = "۱۲۳۴۵۶۷۸۹۰،؛"
|
5
5
|
ENGLISH_CHARS = "1234567890,;"
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
PERSIAN_DIGIT_SPELL = {
|
11
|
-
0 => [ nil ,"یک","دو","سه","چهار","پنج","شش","هفت","هشت","نه", "صفر"] ,
|
12
|
-
1 => [ nil ,"ده","بیست","سی","چهل","پنجاه","شصت","هفتاد","هشتاد","نود"],
|
13
|
-
2 => [ nil ,"صد","دویست","سیصد","چهارصد","پانصد","ششصد","هفتصد","هشتصد","نهصد"],
|
14
|
-
"10..19" => [ "ده" ,"یازده","دوازده","سیزده","چهارده","پانزده","شانزده","هفده","هجده","نوزده"],
|
15
|
-
"zillion" => [ nil ,"هزار","میلیون","میلیارد","بیلیون","تریلیون","کوادریلیون","کوینتیلیون","سیکستیلیون","سپتیلیون","اکتیلیون","نونیلیون","دسیلیون"],
|
16
|
-
"decimals" => [ nil, "دهم", "صدم", "هزارم", "دههزارم", "صدهزارم", "میلیونیم", "دهمیلیونیم","صدمیلیونیم","میلیاردیم"]
|
7
|
+
SIGNS ={
|
8
|
+
"-" => "منفی ",
|
9
|
+
"+" => "مثبت "
|
17
10
|
}
|
18
11
|
|
19
12
|
EXCEPTIONS = {
|
@@ -58,10 +51,11 @@ module FarsiFu
|
|
58
51
|
"نهصد" => 900
|
59
52
|
}
|
60
53
|
|
54
|
+
EXCEPTIONS_INVERT = EXCEPTIONS.invert
|
55
|
+
|
61
56
|
POWER_OF_TEN = {
|
62
|
-
# based on:
|
57
|
+
# based on:
|
63
58
|
# https://fa.wikipedia.org/wiki/%D9%86%D8%A7%D9%85_%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF_%D8%A8%D8%B2%D8%B1%DA%AF
|
64
|
-
"صفر" => 0,
|
65
59
|
"ده" => 1,
|
66
60
|
"هزار" => 3,
|
67
61
|
"میلیون" => 6,
|
@@ -86,4 +80,6 @@ module FarsiFu
|
|
86
80
|
"دسیلیارد" => 63,
|
87
81
|
"گوگول" => 100
|
88
82
|
}
|
83
|
+
|
84
|
+
POWER_OF_TEN_INVERT = POWER_OF_TEN.invert
|
89
85
|
end
|
data/lib/farsifu/num_to_word.rb
CHANGED
@@ -3,8 +3,11 @@
|
|
3
3
|
module FarsiFu
|
4
4
|
class NumToWord
|
5
5
|
|
6
|
-
def initialize(number)
|
7
|
-
@number
|
6
|
+
def initialize(number, verbose = true)
|
7
|
+
@number = number.to_s
|
8
|
+
@sign = check_for_sign
|
9
|
+
@float = true if number.is_a? Float
|
10
|
+
@verbose = verbose
|
8
11
|
end
|
9
12
|
|
10
13
|
# Spells a number in Persian
|
@@ -12,18 +15,12 @@ module FarsiFu
|
|
12
15
|
#
|
13
16
|
# Example:
|
14
17
|
# 5678.spell_farsi # => "پنج هزار و ششصد و هفتاد و هشت"
|
18
|
+
# 3.22.spell_farsi # => "سه ممیز بیست و دو صدم"
|
15
19
|
def spell_farsi
|
16
|
-
|
17
|
-
|
18
|
-
num_array = @number.to_f.to_s.split(".").first.split(//).reverse
|
19
|
-
dec_array = @number.to_f.to_s.split(".").last.split(//).slice(0..9).compact.reverse
|
20
|
-
dec_copy_b = dec_array.clone ; dec_copy_a = dec_array.clone
|
21
|
-
result = spell(num_array)
|
22
|
-
( result += PERSIAN_DIGIT_SIGN[2] + spell(dec_array) + " " + PERSIAN_DIGIT_SPELL["decimals"][dec_copy_a.size].to_s ) unless [PERSIAN_DIGIT_SPELL[0][10],""].include? spell(dec_copy_b)
|
23
|
-
return result
|
20
|
+
if @float
|
21
|
+
parse_and_spell_float
|
24
22
|
else
|
25
|
-
|
26
|
-
return spell(num_array)
|
23
|
+
parse_and_spell_real_number
|
27
24
|
end
|
28
25
|
end
|
29
26
|
|
@@ -34,57 +31,96 @@ module FarsiFu
|
|
34
31
|
# 121.spell_ordinal_farsi # => "صد و بیست و یکم"
|
35
32
|
# 2.spell_ordinal_farsi(true) # => "دومین"
|
36
33
|
# 2054.spell_ordinal_farsi(true) # => "دو هزار و پنجاه چهارمین"
|
37
|
-
def spell_ordinal_farsi(
|
38
|
-
if
|
39
|
-
exceptions = {0 => "صفر", 1 => "اولین", 3 => "سومین"}
|
40
|
-
suffix
|
34
|
+
def spell_ordinal_farsi(second_type = false)
|
35
|
+
if second_type
|
36
|
+
exceptions = {'0' => "صفر", '1' => "اولین", '3' => "سومین"}
|
37
|
+
suffix = "مین"
|
41
38
|
else
|
42
|
-
exceptions = {0 => "صفر", 1 => "اول", 3 => "سوم"}
|
43
|
-
suffix
|
39
|
+
exceptions = {'0' => "صفر", '1' => "اول", '3' => "سوم"}
|
40
|
+
suffix = "م"
|
44
41
|
end
|
45
42
|
|
46
43
|
make_ordinal_spell(exceptions, suffix)
|
47
44
|
end
|
48
45
|
|
49
|
-
private
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
46
|
+
private
|
47
|
+
def parse_and_spell_real_number
|
48
|
+
answer = []
|
49
|
+
group_by_power do |power, num|
|
50
|
+
three_digit_spell = spell_three_digits(num, power)
|
51
|
+
answer.concat three_digit_spell
|
52
|
+
end
|
53
|
+
spell = answer.compact.reverse.join(' و ').prepend("#{SIGNS[@sign]}")
|
54
|
+
# verbose false?
|
55
|
+
spell.gsub!(/^(منفی\s|مثبت\s)*یک\sهزار/) {"#{$1}هزار"} unless @verbose
|
56
|
+
spell
|
57
|
+
end
|
57
58
|
|
58
|
-
|
59
|
-
|
59
|
+
def parse_and_spell_float
|
60
|
+
# Seperate floating point
|
61
|
+
float_num = @number.match(/\./)
|
62
|
+
pre_num, post_num = float_num.pre_match.prepend("#{@sign}"), float_num.post_match
|
63
|
+
# To convert it to دهم, صدم...
|
64
|
+
floating_point_power = 10 ** post_num.size
|
60
65
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
66
|
+
pre_num_spell = NumToWord.new(pre_num).spell_farsi
|
67
|
+
pre_num_spell << 'صفر' if pre_num == '0' and @verbose
|
68
|
+
post_num_spell = NumToWord.new(post_num).spell_farsi
|
69
|
+
floating_point_power_spell = NumToWord.new(floating_point_power, false).spell_ordinal_farsi.gsub(/یک\s*/, '')
|
70
|
+
|
71
|
+
if pre_num != '0' or @verbose
|
72
|
+
"#{pre_num_spell} ممیز #{post_num_spell} #{floating_point_power_spell}"
|
73
|
+
else
|
74
|
+
"#{pre_num_spell if pre_num_spell.size > 0}#{post_num_spell} #{floating_point_power_spell}"
|
65
75
|
end
|
76
|
+
end
|
66
77
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
78
|
+
# checks if the first char is `+` or `-` and returns the sign
|
79
|
+
def check_for_sign
|
80
|
+
sign = @number.slice(0).match(/(-|\+)/)
|
81
|
+
if sign
|
82
|
+
# remove the sign from number
|
83
|
+
@number.slice!(0)
|
84
|
+
sign[1]
|
85
|
+
end
|
86
|
+
end
|
76
87
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
88
|
+
# '1234567' #=> {0=>["7", "6", "5"], 3=>["4", "3", "2"], 6=>["1"]}
|
89
|
+
def group_by_power &block
|
90
|
+
power = 0
|
91
|
+
@number.split('').reverse.each_slice(3) do |digit|
|
92
|
+
yield power, digit
|
93
|
+
power += 3
|
94
|
+
end
|
95
|
+
end
|
83
96
|
|
84
|
-
|
85
|
-
|
97
|
+
# ["7", "6", "5"], 3 #=> ['هفت هزار', 'شصت', 'پانصد']
|
98
|
+
def spell_three_digits(num, power)
|
99
|
+
answer = []
|
100
|
+
yekan = nil
|
101
|
+
num.each_with_index do |n, i|
|
102
|
+
# The 'n' is zero? no need to evaluate
|
103
|
+
next if n == '0'
|
104
|
+
exception_index = n.to_i * (10 ** i)
|
86
105
|
|
87
|
-
|
106
|
+
case i
|
107
|
+
when 0
|
108
|
+
# save Yekan to use for 10..19 exceptions
|
109
|
+
yekan = n
|
110
|
+
when 1
|
111
|
+
# If we're in Sadgan and the digit is 1 so it's a number
|
112
|
+
# between 10..19 and it's an exception
|
113
|
+
if n == '1'
|
114
|
+
exception_index = 10 + yekan.to_i
|
115
|
+
answer.clear
|
116
|
+
end
|
117
|
+
end
|
118
|
+
answer << EXCEPTIONS_INVERT[exception_index]
|
119
|
+
end
|
120
|
+
# append power of ten to first number based on `power` passed to function
|
121
|
+
# ["7", "6", "5"], 3 #=> ['هفت هزار', 'شصت', 'پانصد']
|
122
|
+
answer[0] = "#{answer[0]} #{(POWER_OF_TEN_INVERT[power])}".strip if answer.size > 0
|
123
|
+
answer
|
88
124
|
end
|
89
125
|
|
90
126
|
def make_ordinal_spell(exceptions, suffix)
|
data/lib/farsifu/punch.rb
CHANGED
@@ -10,12 +10,12 @@ module Convert
|
|
10
10
|
end
|
11
11
|
|
12
12
|
module NumToWord
|
13
|
-
def spell_farsi
|
14
|
-
FarsiFu::NumToWord.new(self).spell_farsi
|
13
|
+
def spell_farsi(verbose = true)
|
14
|
+
FarsiFu::NumToWord.new(self, verbose).spell_farsi
|
15
15
|
end
|
16
16
|
|
17
|
-
def spell_ordinal_farsi(
|
18
|
-
FarsiFu::NumToWord.new(self).spell_ordinal_farsi(
|
17
|
+
def spell_ordinal_farsi(second_type = false, verbose = true)
|
18
|
+
FarsiFu::NumToWord.new(self, verbose).spell_ordinal_farsi(second_type)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -27,6 +27,7 @@ end
|
|
27
27
|
|
28
28
|
class String
|
29
29
|
include Convert
|
30
|
+
include NumToWord
|
30
31
|
include WordToNum
|
31
32
|
end
|
32
33
|
|
@@ -34,8 +35,3 @@ class Numeric
|
|
34
35
|
include Convert
|
35
36
|
include NumToWord
|
36
37
|
end
|
37
|
-
|
38
|
-
# Seems that Numeric works for both Float and Integers
|
39
|
-
# class Float
|
40
|
-
# include NumToWord
|
41
|
-
# end
|
data/lib/farsifu/version.rb
CHANGED
data/spec/farsifu_spec.rb
CHANGED
@@ -22,6 +22,7 @@ describe "Farsifu" do
|
|
22
22
|
it "should be able to spell positive and negetive integers in Persian" do
|
23
23
|
1024.spell_farsi.should == "یک هزار و بیست و چهار"
|
24
24
|
-2567023.spell_farsi.should == "منفی دو میلیون و پانصد و شصت و هفت هزار و بیست و سه"
|
25
|
+
'+2567023'.spell_farsi.should == "مثبت دو میلیون و پانصد و شصت و هفت هزار و بیست و سه"
|
25
26
|
end
|
26
27
|
|
27
28
|
it "should be able to spell positive and negetive floats in Persian" do
|
@@ -32,6 +33,13 @@ describe "Farsifu" do
|
|
32
33
|
-0.999.spell_farsi.should == "منفی صفر ممیز نهصد و نود و نه هزارم"
|
33
34
|
end
|
34
35
|
|
36
|
+
it "should spell in non-verbose mode" do
|
37
|
+
1204.spell_farsi(false).should eq('هزار و دویست و چهار')
|
38
|
+
-0.2.spell_farsi(false).should eq('منفی دو دهم')
|
39
|
+
# shouldn't affect floats without zero at the beginning
|
40
|
+
1.2.spell_farsi(false).should eq('یک ممیز دو دهم')
|
41
|
+
end
|
42
|
+
|
35
43
|
it "should be able to show first type of sequentional numbers to persian" do
|
36
44
|
nums = {0 => "صفر",1 => "اول", 3 => "سوم", 12 => "دوازدهم", 33 => "سی و سوم", 121=> "صد و بیست و یکم"}
|
37
45
|
nums.each do |k, v|
|
metadata
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: farsifu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Allen A. Bargi
|
9
|
+
- Arash Mousavi
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date: 2013-02-
|
13
|
+
date: 2013-02-15 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: rspec
|
@@ -61,7 +62,7 @@ dependencies:
|
|
61
62
|
version: '0'
|
62
63
|
description: a toolbox for developing ruby applications in Persian (Farsi) language,
|
63
64
|
see readme file for features
|
64
|
-
email: allen.bargi@gmail.com
|
65
|
+
email: allen.bargi@gmail.com mousavi.arash@gmail.com
|
65
66
|
executables: []
|
66
67
|
extensions: []
|
67
68
|
extra_rdoc_files:
|