farsifu 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|