Import python-num2words_0.5.9.orig.tar.gz

[dgit import orig python-num2words_0.5.9.orig.tar.gz]
This commit is contained in:
Raphaël Hertzog 2021-01-19 16:16:13 +01:00
commit 141ea80332
92 changed files with 15730 additions and 0 deletions

5
.coveragerc Normal file
View File

@ -0,0 +1,5 @@
[run]
branch = true
source =
num2words
tests

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
*.pyc
build
dist
.idea/
*.egg-info
/.tox

20
.travis.yml Normal file
View File

@ -0,0 +1,20 @@
sudo: false
language: python
python:
- "2.7"
- "3.4"
- "3.5"
- "3.6"
matrix:
include:
- { python: 3.6, env: TOXENV=flake8 }
- { python: 3.6, env: TOXENV=isort }
# Py37 requires xenial distrubution and sudo
# See travis-ci/travis-ci#9069
- { python: 3.7, dist: xenial, sudo: true }
install:
- pip install tox-travis
- pip install coveralls
script: tox
after_success: if [ -e .coverage ]; then coveralls; fi

103
CHANGES.rst Normal file
View File

@ -0,0 +1,103 @@
Changelog
=========
Version 0.5.9 -- 2019/01/10
---------------------------
* Fix encoding issue on release 0.5.8 (#229)
* Improve Polish localization (#228)
Version 0.5.8 -- 2018/11/17
---------------------------
* Add Portuguese (Portugal) localization (#198)
* Add a command line tool to use num2words
* Use language iso code for Vietnamese
* Improve Korean localization (#219)
* Improve Serbian (Latin) localization (#207)
* Improve testing setup (#220)
* Improve German localization (#214) (#222)
* Improve Romanian localization (#215)
* Improve Spanish localization (#187) (#200)
* Improve Russian localization (#211) (#212)
* Improve French localization (23902ab)
* Improve Arabic localization (#176)
* Improve Lithuanian and Latvian localization (#185)
* Improve Ukrainian localization (#183)
Version 0.5.7 -- 2018/06/27
---------------------------
* Add Finnish localization. (#170)
* Add Japanese localization. (#171)
* Add belgian-french localization. (#151)
* Add Czech localization. (#154)
* Add Thai localization. (#139)
* Improve English localization. (#144)
* Improve Spanish localization. (#167)
* Improve Italian localization. (#143)
* Improve documentation. (#155, #145, #174)
Version 0.5.6 -- 2017/11/22
---------------------------
* Refactor to_currency (#135)
* Allow the use of other convertes to_currency, to_year (#95)
* Fix code to respect PEP8 (#98, #105)
* Add Slovene localization (#97)
* Add Ukrainian localization (#93)
* Add Dutch localization (#91)
* Add Algeria-French localization (#86)
* Add Turkish localization (#85)
Version 0.5.5 -- 2017/07/02
---------------------------
* Add Arabic localization (#72)
* Add Spanish-Colombian and Spanish-Venezuelan localization (#67)
* Add VietNam localization (#61)
* Add Italian localization (#56, #59)
* Improve Russian localization (#62)
* Improve Polish localization (#58)
Version 0.5.4 -- 2016/10/18
---------------------------
* Tons of new languages!
* Add Polish localization. (#23)
* Add Swiss-French localization. (#38)
* Add Russian localization. (#28, #46, #48)
* Add Indonesian localization. (#29)
* Add Norwegian localization. (#33)
* Add Danish localization. (#40)
* Add Brazilian localization. (#37, #47)
* Improve German localization. (#25, #27, #49)
* Improve Lithuanian localization. (#52)
* Improve floating point spelling. (#24)
Version 0.5.3 -- 2015/06/09
---------------------------
* Fix packaging issues. (#21, #22)
Version 0.5.2 -- 2015/01/23
---------------------------
* Added Latvian localization. (#9)
* Improved Spanish localization. (#10, #13, #14)
* Improved Lithuanian localization. (#12)
Version 0.5.1 -- 2014/03/14
---------------------------
* Added Python 3 support with 2to3. (#3)
* Fixed big numbers in spanish. (#2)
* Fixed bugs in tanslation from 30 to 40 in spanish. (#4)
* Fixed word joining in english. (#8)
Version 0.5.0 -- 2013/05/28
---------------------------
* Created ``num2words`` based on the old ``pynum2word`` project.

46
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at support@savoirfairelinux.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

53
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,53 @@
## How can I contribute ?
### Code contribution
#### Issues
If you are unsure where to begin contribution to Num2Words, you can start by looking through the issues page.
Numerous issues are created and waiting for your love on the [issue board](https://github.com/savoirfairelinux/num2words/issues).
#### Pull Requests
Contributions will be accepted through the creation of Pull Requests. Here is the workflow:
* Fork the repository into yours and work from there
* Commit and push your changes into your fork
* When you are done, create a [Pull Request](https://github.com/savoirfairelinux/num2words/compare) on the **master** branch
A template is provided to create your Pull Request. Try to fill the information at the best of your knowledge.
#### Pull request checklist
For your pull request to be merged, the answer to the following questions must be 'yes':
##### General
* Can the branch be merged automatically?
##### Testing
* Do the unit tests pass?
##### Adding new code
* Is the code PEP8 compliant?
* Is the code covered by tests?
[TravisCI](https://travis-ci.org/) is configured to run those checks on every Pull-Request. It is recommended you configure your fork to do the same.
### Reporting bugs
Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/).
#### How to submit a good bug report
Please include as many details as possible. An issue template is automatically loaded when you create an issue.
* Use a clear and comprehensive title for the issue
* Describe the expected behaviour in as many details as possible
* Describe the actual behaviour in as many details as possible
### Testing the application
Our development process is based on Continuous Integration. We love to have a nice code coverage!

145
COPYING Normal file
View File

@ -0,0 +1,145 @@
GNU Lesser General Public License
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.]
Preamble
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.
To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others.
Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs.
When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library.
We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances.
For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.
Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library.
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library.
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful.
(For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.)
These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library.
In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices.
Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange.
If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:
a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.
e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute.
7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above.
b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License.
11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS

13
ISSUE_TEMPLATE.md Normal file
View File

@ -0,0 +1,13 @@
### Expected Behaviour
Fill me in ...
### Actual Behaviour
Fill me in ...
### Steps to reproduce
* step 1
* step 2
* ...

4
MANIFEST.in Normal file
View File

@ -0,0 +1,4 @@
include CHANGES.rst
include COPYING
include tests/*
include bin/num2words

21
PULL_REQUEST_TEMPLATE.md Normal file
View File

@ -0,0 +1,21 @@
## Fixes # by...
### Changes proposed in this pull request:
* ...
* ...
### Status
- [ ] READY
- [ ] HOLD
- [X] WIP (Work-In-Progress)
### How to verify this change
*Fill out this section so that a reviewer can know how to verify your change.*
### Additional notes
*If applicable, explain the rationale behind your change.*

147
README.rst Normal file
View File

@ -0,0 +1,147 @@
num2words - Convert numbers to words in multiple languages
==========================================================
.. image:: https://img.shields.io/pypi/v/num2words.svg
:target: https://pypi.python.org/pypi/num2words
.. image:: https://travis-ci.org/savoirfairelinux/num2words.svg?branch=master
:target: https://travis-ci.org/savoirfairelinux/num2words
.. image:: https://coveralls.io/repos/github/savoirfairelinux/num2words/badge.svg?branch=master
:target: https://coveralls.io/github/savoirfairelinux/num2words?branch=master
``num2words`` is a library that converts numbers like ``42`` to words like ``forty-two``.
It supports multiple languages (see the list below for full list
of languages) and can even generate ordinal numbers like ``forty-second``
(although this last feature is a bit buggy for some languages at the moment).
The project is hosted on GitHub_. Contributions are welcome.
.. _GitHub: https://github.com/savoirfairelinux/num2words
Installation
------------
The easiest way to install ``num2words`` is to use pip::
pip install num2words
Otherwise, you can download the source package and then execute::
python setup.py install
The test suite in this library is new, so it's rather thin, but it can be run with::
python setup.py test
To run the full CI test suite which includes linting and multiple python environments::
pip install tox
tox
Usage
-----
Command line::
$ num2words 10001
ten thousand and one
$ num2words 24,120.10
twenty-four thousand, one hundred and twenty point one
$ num2words 24,120.10 -l es
veinticuatro mil ciento veinte punto uno
$num2words 2.14 -l es --to currency
dos euros con catorce centimos
In code there's only one function to use::
>>> from num2words import num2words
>>> num2words(42)
forty-two
>>> num2words(42, to='ordinal')
forty-second
>>> num2words(42, lang='fr')
quarante-deux
Besides the numerical argument, there are two main optional arguments.
**to:** The converter to use. Supported values are:
* ``cardinal`` (default)
* ``ordinal``
* ``ordinal_num``
* ``year``
* ``currency``
**lang:** The language in which to convert the number. Supported values are:
* ``en`` (English, default)
* ``ar`` (Arabic)
* ``cz`` (Czech)
* ``de`` (German)
* ``dk`` (Danish)
* ``en_GB`` (English - Great Britain)
* ``en_IN`` (English - India)
* ``es`` (Spanish)
* ``es_CO`` (Spanish - Colombia)
* ``es_VE`` (Spanish - Venezuela)
* ``eu`` (EURO)
* ``fi`` (Finnish)
* ``fr`` (French)
* ``fr_CH`` (French - Switzerland)
* ``fr_BE`` (French - Belgium)
* ``fr_DZ`` (French - Algeria)
* ``he`` (Hebrew)
* ``id`` (Indonesian)
* ``it`` (Italian)
* ``ja`` (Japanese)
* ``ko`` (Korean)
* ``lt`` (Lithuanian)
* ``lv`` (Latvian)
* ``no`` (Norwegian)
* ``pl`` (Polish)
* ``pt`` (Portuguese)
* ``pt_BR`` (Portuguese - Brazilian)
* ``sl`` (Slovene)
* ``sr`` (Serbian)
* ``ro`` (Romanian)
* ``ru`` (Russian)
* ``sl`` (Slovene)
* ``tr`` (Turkish)
* ``th`` (Thai)
* ``vi`` (Vietnamese)
* ``nl`` (Dutch)
* ``uk`` (Ukrainian)
You can supply values like ``fr_FR``; if the country doesn't exist but the
language does, the code will fall back to the base language (i.e. ``fr``). If
you supply an unsupported language, ``NotImplementedError`` is raised.
Therefore, if you want to call ``num2words`` with a fallback, you can do::
try:
return num2words(42, lang=mylang)
except NotImplementedError:
return num2words(42, lang='en')
Additionally, some converters and languages support other optional arguments
that are needed to make the converter useful in practice.
Wiki
----
For additional information on some localization please check the Wiki_.
And feel free to propose wiki enhancement.
.. _Wiki: https://github.com/savoirfairelinux/num2words/wiki
History
-------
``num2words`` is based on an old library, ``pynum2word``, created by Taro Ogawa
in 2003. Unfortunately, the library stopped being maintained and the author
can't be reached. There was another developer, Marius Grigaitis, who in 2011
added Lithuanian support, but didn't take over maintenance of the project.
I am thus basing myself on Marius Grigaitis' improvements and re-publishing
``pynum2word`` as ``num2words``.
Virgil Dupras, Savoir-faire Linux

95
bin/num2words Executable file
View File

@ -0,0 +1,95 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
"""num2words: convert numbers into words.
Usage:
num2words [options] <number>
num2words --list-languages
num2words --list-converters
num2words --help
Arguments:
<number> Number you want to convert into words
Options:
-L --list-languages Show all languages.
-C --list-converters Show all converters.
-l --lang=<lang> Output language [default: en].
-t --to=<to> Output converter [default: cardinal].
-h --help Show this message.
-v --version Show version.
Examples:
$ num2words 10001
ten thousand and one
$ num2words 24,120.10
twenty-four thousand, one hundred and twenty point one
$ num2words 24,120.10 -l es
veinticuatro mil ciento veinte punto uno
$num2words 2.14 -l es --to currency
dos euros con catorce centimos
"""
from __future__ import print_function, unicode_literals
import os
import sys
from docopt import docopt
import num2words
__version__ = "0.5.9"
__license__ = "LGPL"
def get_languages():
return sorted(list(num2words.CONVERTER_CLASSES.keys()))
def get_converters():
return sorted(list(num2words.CONVERTES_TYPES))
def main():
version = "{}=={}".format(os.path.basename(__file__), __version__)
args = docopt(__doc__, argv=None, help=True, version=version, options_first=False)
if args["--list-languages"]:
for lang in get_languages():
sys.stdout.write(lang)
sys.stdout.write(os.linesep)
sys.exit(0)
if args["--list-converters"]:
for lang in get_converters():
sys.stdout.write(lang)
sys.stdout.write(os.linesep)
sys.exit(0)
try:
words = num2words.num2words(args['<number>'], lang=args['--lang'], to=args['--to'])
sys.stdout.write(words+os.linesep)
sys.exit(0)
except Exception as err:
sys.stderr.write(str(args['<number>']))
sys.stderr.write(str(err) + os.linesep)
sys.stderr.write(__doc__)
sys.exit(1)
if __name__ == '__main__':
main()

7
docker-compose.yml Normal file
View File

@ -0,0 +1,7 @@
version: '3.0'
services:
web:
image: python:3-alpine
command: python3 -m http.server 8080
volumes:
- .:/num2words

111
num2words/__init__.py Normal file
View File

@ -0,0 +1,111 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from . import lang_AR
from . import lang_CZ
from . import lang_EN
from . import lang_EN_IN
from . import lang_FR
from . import lang_FR_CH
from . import lang_FR_BE
from . import lang_FR_DZ
from . import lang_DE
from . import lang_ES
from . import lang_FI
from . import lang_LT
from . import lang_LV
from . import lang_PL
from . import lang_RO
from . import lang_RU
from . import lang_ID
from . import lang_JA
from . import lang_NO
from . import lang_DK
from . import lang_PT
from . import lang_PT_BR
from . import lang_HE
from . import lang_IT
from . import lang_ES_VE
from . import lang_ES_CO
from . import lang_VI
from . import lang_TR
from . import lang_NL
from . import lang_UK
from . import lang_SL
from . import lang_SR
from . import lang_TH
from . import lang_KO
CONVERTER_CLASSES = {
'ar': lang_AR.Num2Word_AR(),
'cz': lang_CZ.Num2Word_CZ(),
'en': lang_EN.Num2Word_EN(),
'en_IN': lang_EN_IN.Num2Word_EN_IN(),
'fr': lang_FR.Num2Word_FR(),
'fr_CH': lang_FR_CH.Num2Word_FR_CH(),
'fr_BE': lang_FR_BE.Num2Word_FR_BE(),
'fr_DZ': lang_FR_DZ.Num2Word_FR_DZ(),
'de': lang_DE.Num2Word_DE(),
'fi': lang_FI.Num2Word_FI(),
'es': lang_ES.Num2Word_ES(),
'es_CO': lang_ES_CO.Num2Word_ES_CO(),
'es_VE': lang_ES_VE.Num2Word_ES_VE(),
'id': lang_ID.Num2Word_ID(),
'ja': lang_JA.Num2Word_JA(),
'ko': lang_KO.Num2Word_KO(),
'lt': lang_LT.Num2Word_LT(),
'lv': lang_LV.Num2Word_LV(),
'pl': lang_PL.Num2Word_PL(),
'ro': lang_RO.Num2Word_RO(),
'ru': lang_RU.Num2Word_RU(),
'sl': lang_SL.Num2Word_SL(),
'sr': lang_SR.Num2Word_SR(),
'no': lang_NO.Num2Word_NO(),
'dk': lang_DK.Num2Word_DK(),
'pt': lang_PT.Num2Word_PT(),
'pt_BR': lang_PT_BR.Num2Word_PT_BR(),
'he': lang_HE.Num2Word_HE(),
'it': lang_IT.Num2Word_IT(),
'vi': lang_VI.Num2Word_VI(),
'th': lang_TH.Num2Word_TH(),
'tr': lang_TR.Num2Word_TR(),
'nl': lang_NL.Num2Word_NL(),
'uk': lang_UK.Num2Word_UK()
}
CONVERTES_TYPES = ['cardinal', 'ordinal', 'ordinal_num', 'year', 'currency']
def num2words(number, ordinal=False, lang='en', to='cardinal', **kwargs):
# We try the full language first
if lang not in CONVERTER_CLASSES:
# ... and then try only the first 2 letters
lang = lang[:2]
if lang not in CONVERTER_CLASSES:
raise NotImplementedError()
converter = CONVERTER_CLASSES[lang]
# backwards compatible
if ordinal:
return converter.to_ordinal(number)
if to not in CONVERTES_TYPES:
raise NotImplementedError()
return getattr(converter, 'to_{}'.format(to))(number, **kwargs)

303
num2words/base.py Normal file
View File

@ -0,0 +1,303 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
import math
from collections import OrderedDict
from decimal import Decimal
from .compat import to_s
from .currency import parse_currency_parts, prefix_currency
class Num2Word_Base(object):
CURRENCY_FORMS = {}
CURRENCY_ADJECTIVES = {}
def __init__(self):
self.is_title = False
self.precision = 2
self.exclude_title = []
self.negword = "(-) "
self.pointword = "(.)"
self.errmsg_nonnum = "type(%s) not in [long, int, float]"
self.errmsg_floatord = "Cannot treat float %s as ordinal."
self.errmsg_negord = "Cannot treat negative num %s as ordinal."
self.errmsg_toobig = "abs(%s) must be less than %s."
self.setup()
# uses cards
if any(hasattr(self, field) for field in
['high_numwords', 'mid_numwords', 'low_numwords']):
self.cards = OrderedDict()
self.set_numwords()
self.MAXVAL = 1000 * list(self.cards.keys())[0]
def set_numwords(self):
self.set_high_numwords(self.high_numwords)
self.set_mid_numwords(self.mid_numwords)
self.set_low_numwords(self.low_numwords)
def set_high_numwords(self, *args):
raise NotImplementedError
def set_mid_numwords(self, mid):
for key, val in mid:
self.cards[key] = val
def set_low_numwords(self, numwords):
for word, n in zip(numwords, range(len(numwords) - 1, -1, -1)):
self.cards[n] = word
def splitnum(self, value):
for elem in self.cards:
if elem > value:
continue
out = []
if value == 0:
div, mod = 1, 0
else:
div, mod = divmod(value, elem)
if div == 1:
out.append((self.cards[1], 1))
else:
if div == value: # The system tallies, eg Roman Numerals
return [(div * self.cards[elem], div*elem)]
out.append(self.splitnum(div))
out.append((self.cards[elem], elem))
if mod:
out.append(self.splitnum(mod))
return out
def parse_minus(self, num_str):
"""Detach minus and return it as symbol with new num_str."""
if num_str.startswith('-'):
# Extra spacing to compensate if there is no minus.
return '%s ' % self.negword, num_str[1:]
return '', num_str
def to_cardinal(self, value):
try:
assert int(value) == value
except (ValueError, TypeError, AssertionError):
return self.to_cardinal_float(value)
out = ""
if value < 0:
value = abs(value)
out = self.negword
if value >= self.MAXVAL:
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
val = self.splitnum(value)
words, num = self.clean(val)
return self.title(out + words)
def float2tuple(self, value):
pre = int(value)
# Simple way of finding decimal places to update the precision
self.precision = abs(Decimal(str(value)).as_tuple().exponent)
post = abs(value - pre) * 10**self.precision
if abs(round(post) - post) < 0.01:
# We generally floor all values beyond our precision (rather than
# rounding), but in cases where we have something like 1.239999999,
# which is probably due to python's handling of floats, we actually
# want to consider it as 1.24 instead of 1.23
post = int(round(post))
else:
post = int(math.floor(post))
return pre, post
def to_cardinal_float(self, value):
try:
float(value) == value
except (ValueError, TypeError, AssertionError):
raise TypeError(self.errmsg_nonnum % value)
pre, post = self.float2tuple(float(value))
post = str(post)
post = '0' * (self.precision - len(post)) + post
out = [self.to_cardinal(pre)]
if self.precision:
out.append(self.title(self.pointword))
for i in range(self.precision):
curr = int(post[i])
out.append(to_s(self.to_cardinal(curr)))
return " ".join(out)
def merge(self, curr, next):
raise NotImplementedError
def clean(self, val):
out = val
while len(val) != 1:
out = []
left, right = val[:2]
if isinstance(left, tuple) and isinstance(right, tuple):
out.append(self.merge(left, right))
if val[2:]:
out.append(val[2:])
else:
for elem in val:
if isinstance(elem, list):
if len(elem) == 1:
out.append(elem[0])
else:
out.append(self.clean(elem))
else:
out.append(elem)
val = out
return out[0]
def title(self, value):
if self.is_title:
out = []
value = value.split()
for word in value:
if word in self.exclude_title:
out.append(word)
else:
out.append(word[0].upper() + word[1:])
value = " ".join(out)
return value
def verify_ordinal(self, value):
if not value == int(value):
raise TypeError(self.errmsg_floatord % value)
if not abs(value) == value:
raise TypeError(self.errmsg_negord % value)
def to_ordinal(self, value):
return self.to_cardinal(value)
def to_ordinal_num(self, value):
return value
# Trivial version
def inflect(self, value, text):
text = text.split("/")
if value == 1:
return text[0]
return "".join(text)
# //CHECK: generalise? Any others like pounds/shillings/pence?
def to_splitnum(self, val, hightxt="", lowtxt="", jointxt="",
divisor=100, longval=True, cents=True):
out = []
if isinstance(val, float):
high, low = self.float2tuple(val)
else:
try:
high, low = val
except TypeError:
high, low = divmod(val, divisor)
if high:
hightxt = self.title(self.inflect(high, hightxt))
out.append(self.to_cardinal(high))
if low:
if longval:
if hightxt:
out.append(hightxt)
if jointxt:
out.append(self.title(jointxt))
elif hightxt:
out.append(hightxt)
if low:
if cents:
out.append(self.to_cardinal(low))
else:
out.append("%02d" % low)
if lowtxt and longval:
out.append(self.title(self.inflect(low, lowtxt)))
return " ".join(out)
def to_year(self, value, **kwargs):
return self.to_cardinal(value)
def pluralize(self, n, forms):
"""
Should resolve gettext form:
http://docs.translatehouse.org/projects/localization-guide/en/latest/l10n/pluralforms.html
"""
raise NotImplementedError
def _cents_verbose(self, number, currency):
return self.to_cardinal(number)
def _cents_terse(self, number, currency):
return "%02d" % number
def to_currency(self, val, currency='EUR', cents=True, seperator=',',
adjective=False):
"""
Args:
val: Numeric value
currency (str): Currency code
cents (bool): Verbose cents
seperator (str): Cent seperator
adjective (bool): Prefix currency name with adjective
Returns:
str: Formatted string
"""
left, right, is_negative = parse_currency_parts(val)
try:
cr1, cr2 = self.CURRENCY_FORMS[currency]
except KeyError:
raise NotImplementedError(
'Currency code "%s" not implemented for "%s"' %
(currency, self.__class__.__name__))
if adjective and currency in self.CURRENCY_ADJECTIVES:
cr1 = prefix_currency(self.CURRENCY_ADJECTIVES[currency], cr1)
minus_str = "%s " % self.negword if is_negative else ""
cents_str = self._cents_verbose(right, currency) \
if cents else self._cents_terse(right, currency)
return u'%s%s %s%s %s %s' % (
minus_str,
self.to_cardinal(left),
self.pluralize(left, cr1),
seperator,
cents_str,
self.pluralize(right, cr2)
)
def setup(self):
pass

29
num2words/compat.py Normal file
View File

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
try:
strtype = basestring
except NameError:
strtype = str
def to_s(val):
try:
return unicode(val)
except NameError:
return str(val)

50
num2words/currency.py Normal file
View File

@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import division
from decimal import ROUND_HALF_UP, Decimal
def parse_currency_parts(value, is_int_with_cents=True):
if isinstance(value, int):
if is_int_with_cents:
# assume cents if value is integer
negative = value < 0
value = abs(value)
integer, cents = divmod(value, 100)
else:
negative = value < 0
integer, cents = abs(value), 0
else:
value = Decimal(value)
value = value.quantize(
Decimal('.01'),
rounding=ROUND_HALF_UP
)
negative = value < 0
value = abs(value)
integer, fraction = divmod(value, 1)
integer = int(integer)
cents = int(fraction * 100)
return integer, cents, negative
def prefix_currency(prefix, base):
return tuple("%s %s" % (prefix, i) for i in base)

352
num2words/lang_AR.py Normal file
View File

@ -0,0 +1,352 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# Copyright (c) 2018, Abdullah Alhazmy, Alhazmy13. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
import re
from decimal import Decimal
from math import floor
CURRENCY_SR = [("ريال", "ريالان", "ريالات", "ريالاً"),
("هللة", "هللتان", "هللات", "هللة")]
CURRENCY_EGP = [("جنيه", "جنيهان", "جنيهات", "جنيهاً"),
("قرش", "قرشان", "قروش", "قرش")]
CURRENCY_KWD = [("دينار", "ديناران", "دينارات", "ديناراً"),
("فلس", "فلسان", "فلس", "فلس")]
ARABIC_ONES = [
"", "واحد", "اثنان", "ثلاثة", "أربعة", "خمسة", "ستة", "سبعة", "ثمانية",
"تسعة",
"عشرة", "أحد عشر", "اثنا عشر", "ثلاثة عشر", "أربعة عشر", "خمسة عشر",
"ستة عشر", "سبعة عشر", "ثمانية عشر",
"تسعة عشر"
]
class Num2Word_AR(object):
errmsg_too_big = "Too large"
max_num = 10 ** 36
def __init__(self):
self.number = 0
self.arabicPrefixText = ""
self.arabicSuffixText = ""
self.integer_value = 0
self._decimalValue = ""
self.partPrecision = 2
self.currency_unit = CURRENCY_SR[0]
self.currency_subunit = CURRENCY_SR[1]
self.isCurrencyPartNameFeminine = True
self.isCurrencyNameFeminine = False
self.separator = 'و'
self.arabicOnes = ARABIC_ONES
self.arabicFeminineOnes = [
"", "إحدى", "اثنتان", "ثلاث", "أربع", "خمس", "ست", "سبع", "ثمان",
"تسع",
"عشر", "إحدى عشرة", "اثنتا عشرة", "ثلاث عشرة", "أربع عشرة",
"خمس عشرة", "ست عشرة", "سبع عشرة", "ثماني عشرة",
"تسع عشرة"
]
self.arabicOrdinal = [
"", "اول", "ثاني", "ثالث", "رابع", "خامس", "سادس", "سابع", "ثامن",
"تاسع", "عاشر", "حادي عشر", "ثاني عشر", "ثالث عشر", "رابع عشر",
"خامس عشر", "سادس عشر", "سابع عشر", "ثامن عشر", "تاسع عشر"
]
self.arabicTens = [
"عشرون", "ثلاثون", "أربعون", "خمسون", "ستون", "سبعون", "ثمانون",
"تسعون"
]
self.arabicHundreds = [
"", "مائة", "مئتان", "ثلاثمائة", "أربعمائة", "خمسمائة", "ستمائة",
"سبعمائة", "ثمانمائة", "تسعمائة"
]
self.arabicAppendedTwos = [
"مئتا", "ألفا", "مليونا", "مليارا", "تريليونا", "كوادريليونا",
"كوينتليونا", "سكستيليونا"
]
self.arabicTwos = [
"مئتان", "ألفان", "مليونان", "ملياران", "تريليونان",
"كوادريليونان", "كوينتليونان", "سكستيليونان"
]
self.arabicGroup = [
"مائة", "ألف", "مليون", "مليار", "تريليون", "كوادريليون",
"كوينتليون", "سكستيليون"
]
self.arabicAppendedGroup = [
"", "ألفاً", "مليوناً", "ملياراً", "تريليوناً", "كوادريليوناً",
"كوينتليوناً", "سكستيليوناً"
]
self.arabicPluralGroups = [
"", "آلاف", "ملايين", "مليارات", "تريليونات", "كوادريليونات",
"كوينتليونات", "سكستيليونات"
]
def number_to_arabic(self, arabic_prefix_text, arabic_suffix_text):
self.arabicPrefixText = arabic_prefix_text
self.arabicSuffixText = arabic_suffix_text
self.extract_integer_and_decimal_parts()
def extract_integer_and_decimal_parts(self):
re.split('\\.', str(self.number))
splits = re.split('\\.', str(self.number))
self.integer_value = int(splits[0])
if len(splits) > 1:
self._decimalValue = int(self.decimal_value(splits[1]))
else:
self._decimalValue = 0
def decimal_value(self, decimal_part):
if self.partPrecision is not len(decimal_part):
decimal_part_length = len(decimal_part)
decimal_part_builder = decimal_part
for i in range(0, self.partPrecision - decimal_part_length):
decimal_part_builder += '0'
decimal_part = decimal_part_builder
if len(decimal_part) <= self.partPrecision:
dec = len(decimal_part)
else:
dec = self.partPrecision
result = decimal_part[0: dec]
else:
result = decimal_part
for i in range(len(result), self.partPrecision):
result += '0'
return result
def digit_feminine_status(self, digit, group_level):
if group_level == -1:
if self.isCurrencyPartNameFeminine:
return self.arabicFeminineOnes[int(digit)]
else:
return self.arabicOnes[int(digit)]
elif group_level == 0:
if self.isCurrencyNameFeminine:
return self.arabicFeminineOnes[int(digit)]
else:
return self.arabicOnes[int(digit)]
else:
return self.arabicOnes[int(digit)]
def process_arabic_group(self, group_number, group_level,
remaining_number):
tens = Decimal(group_number) % Decimal(100)
hundreds = Decimal(group_number) / Decimal(100)
ret_val = ""
if int(hundreds) > 0:
if tens == 0 and int(hundreds) == 2:
ret_val = "{}".format(self.arabicAppendedTwos[0])
else:
ret_val = "{}".format(self.arabicHundreds[int(hundreds)])
if tens > 0:
if tens < 20:
if tens == 2 and int(hundreds) == 0 and group_level > 0:
if self.integer_value in [2000, 2000000, 2000000000,
2000000000000, 2000000000000000,
2000000000000000000]:
ret_val = "{}".format(
self.arabicAppendedTwos[int(group_level)])
else:
ret_val = "{}".format(
self.arabicTwos[int(group_level)])
else:
if ret_val != "":
ret_val += " و "
if tens == 1 and group_level > 0 and hundreds == 0:
ret_val += ""
elif (tens == 1 or tens == 2) and (
group_level == 0 or group_level == -1) and \
hundreds == 0 and remaining_number == 0:
ret_val += ""
else:
ret_val += self.digit_feminine_status(int(tens),
group_level)
else:
ones = tens % 10
tens = (tens / 10) - 2
if ones > 0:
if ret_val is not "" and tens < 4:
ret_val += " و "
ret_val += self.digit_feminine_status(ones, group_level)
if ret_val is not "" and ones != 0:
ret_val += " و "
ret_val += self.arabicTens[int(tens)]
return ret_val
def convert(self, value):
self.number = "{:.9f}".format(value)
self.number_to_arabic(self.arabicPrefixText, self.arabicSuffixText)
return self.convert_to_arabic()
def convert_to_arabic(self):
temp_number = Decimal(self.number)
if temp_number == Decimal(0):
return "صفر"
decimal_string = self.process_arabic_group(self._decimalValue,
-1,
Decimal(0))
ret_val = ""
group = 0
while temp_number > Decimal(0):
number_to_process = int(
Decimal(str(temp_number)) % Decimal(str(1000)))
temp_number = int(Decimal(temp_number) / Decimal(1000))
group_description = \
self.process_arabic_group(number_to_process,
group,
Decimal(floor(temp_number)))
if group_description is not '':
if group > 0:
if ret_val is not "":
ret_val = "{} و {}".format("", ret_val)
if number_to_process != 2:
if number_to_process % 100 != 1:
if 3 <= number_to_process <= 10:
ret_val = "{} {}".format(
self.arabicPluralGroups[group], ret_val)
else:
if ret_val is not "":
ret_val = "{} {}".format(
self.arabicAppendedGroup[group],
ret_val)
else:
ret_val = "{} {}".format(
self.arabicGroup[group], ret_val)
else:
ret_val = "{} {}".format(self.arabicGroup[group],
ret_val)
ret_val = "{} {}".format(group_description, ret_val)
group += 1
formatted_number = ""
if self.arabicPrefixText is not "":
formatted_number += "{} ".format(self.arabicPrefixText)
formatted_number += ret_val
if self.integer_value != 0:
remaining100 = int(self.integer_value % 100)
if remaining100 == 0:
formatted_number += self.currency_unit[0]
elif remaining100 == 1:
formatted_number += self.currency_unit[0]
elif remaining100 == 2:
if self.integer_value == 2:
formatted_number += self.currency_unit[1]
else:
formatted_number += self.currency_unit[0]
elif 3 <= remaining100 <= 10:
formatted_number += self.currency_unit[2]
elif 11 <= remaining100 <= 99:
formatted_number += self.currency_unit[3]
if self._decimalValue != 0:
formatted_number += " {} ".format(self.separator)
formatted_number += decimal_string
if self._decimalValue != 0:
formatted_number += " "
remaining100 = int(self._decimalValue % 100)
if remaining100 == 0:
formatted_number += self.currency_subunit[0]
elif remaining100 == 1:
formatted_number += self.currency_subunit[0]
elif remaining100 == 2:
formatted_number += self.currency_subunit[1]
elif 3 <= remaining100 <= 10:
formatted_number += self.currency_subunit[2]
elif 11 <= remaining100 <= 99:
formatted_number += self.currency_subunit[3]
if self.arabicSuffixText is not "":
formatted_number += " {}".format(self.arabicSuffixText)
return formatted_number
def validate_number(self, number):
if number >= self.max_num:
raise OverflowError(self.errmsg_too_big)
return number
def set_currency_prefer(self, currency):
if currency is 'EGP':
self.currency_unit = CURRENCY_EGP[0]
self.currency_subunit = CURRENCY_EGP[1]
elif currency is 'KWD':
self.currency_unit = CURRENCY_KWD[0]
self.currency_subunit = CURRENCY_KWD[1]
else:
self.currency_unit = CURRENCY_SR[0]
self.currency_subunit = CURRENCY_SR[1]
def to_currency(self, value, currency='SR', prefix='', suffix=''):
self.set_currency_prefer(currency)
self.isCurrencyNameFeminine = False
self.separator = "و"
self.arabicOnes = ARABIC_ONES
self.arabicPrefixText = prefix
self.arabicSuffixText = suffix
return self.convert(value=value)
def to_ordinal(self, number, prefix=''):
if number <= 19:
return "{}".format(self.arabicOrdinal[number])
if number < 100:
self.isCurrencyNameFeminine = True
else:
self.isCurrencyNameFeminine = False
self.currency_subunit = ('', '', '', '')
self.currency_unit = ('', '', '', '')
self.arabicPrefixText = prefix
self.arabicSuffixText = ""
return "{}".format(self.convert(abs(number)).strip())
def to_year(self, value):
value = self.validate_number(value)
return self.to_cardinal(value)
def to_ordinal_num(self, value):
return self.to_ordinal(value).strip()
def to_cardinal(self, number):
number = self.validate_number(number)
minus = ''
if number < 0:
minus = 'سالب '
self.separator = ','
self.currency_subunit = ('', '', '', '')
self.currency_unit = ('', '', '', '')
self.arabicPrefixText = ""
self.arabicSuffixText = ""
self.arabicOnes = ARABIC_ONES
return minus + self.convert(value=abs(number)).strip()

154
num2words/lang_CZ.py Normal file
View File

@ -0,0 +1,154 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from .base import Num2Word_Base
from .utils import get_digits, splitbyx
ZERO = ('nula',)
ONES = {
1: ('jedna',),
2: ('dva',),
3: ('tři',),
4: ('čtyři',),
5: ('pět',),
6: ('šest',),
7: ('sedm',),
8: ('osm',),
9: ('devět',),
}
TENS = {
0: ('deset',),
1: ('jedenáct',),
2: ('dvanáct',),
3: ('třináct',),
4: ('čtrnáct',),
5: ('patnáct',),
6: ('šestnáct',),
7: ('sedmnáct',),
8: ('osmnáct',),
9: ('devatenáct',),
}
TWENTIES = {
2: ('dvacet',),
3: ('třicet',),
4: ('čtyřicet',),
5: ('padesát',),
6: ('šedesát',),
7: ('sedmdesát',),
8: ('osmdesát',),
9: ('devadesát',),
}
HUNDREDS = {
1: ('sto',),
2: ('dvěstě',),
3: ('třista',),
4: ('čtyřista',),
5: ('pětset',),
6: ('šestset',),
7: ('sedmset',),
8: ('osmset',),
9: ('devětset',),
}
THOUSANDS = {
1: ('tisíc', 'tisíce', 'tisíc'), # 10^3
2: ('milion', 'miliony', 'milionů'), # 10^6
3: ('miliarda', 'miliardy', 'miliard'), # 10^9
4: ('bilion', 'biliony', 'bilionů'), # 10^12
5: ('biliarda', 'biliardy', 'biliard'), # 10^15
6: ('trilion', 'triliony', 'trilionů'), # 10^18
7: ('triliarda', 'triliardy', 'triliard'), # 10^21
8: ('kvadrilion', 'kvadriliony', 'kvadrilionů'), # 10^24
9: ('kvadriliarda', 'kvadriliardy', 'kvadriliard'), # 10^27
10: ('quintillion', 'quintilliony', 'quintillionů'), # 10^30
}
class Num2Word_CZ(Num2Word_Base):
CURRENCY_FORMS = {
'CZK': (
('koruna', 'koruny', 'korun'), ('halíř', 'halíře', 'haléřů')
),
'EUR': (
('euro', 'euro', 'euro'), ('cent', 'centy', 'centů')
),
}
def setup(self):
self.negword = "mínus"
self.pointword = "celá"
def to_cardinal(self, number):
n = str(number).replace(',', '.')
if '.' in n:
left, right = n.split('.')
return u'%s %s %s' % (
self._int2word(int(left)),
self.pointword,
self._int2word(int(right))
)
else:
return self._int2word(int(n))
def pluralize(self, n, forms):
if n == 1:
form = 0
elif 5 > n % 10 > 1 and (n % 100 < 10 or n % 100 > 20):
form = 1
else:
form = 2
return forms[form]
def to_ordinal(self, number):
raise NotImplementedError()
def _int2word(self, n):
if n == 0:
return ZERO[0]
words = []
chunks = list(splitbyx(str(n), 3))
i = len(chunks)
for x in chunks:
i -= 1
if x == 0:
continue
n1, n2, n3 = get_digits(x)
if n3 > 0:
words.append(HUNDREDS[n3][0])
if n2 > 1:
words.append(TWENTIES[n2][0])
if n2 == 1:
words.append(TENS[n1][0])
elif n1 > 0 and not (i > 0 and x == 1):
words.append(ONES[n1][0])
if i > 0:
words.append(self.pluralize(x, THOUSANDS[i]))
return ' '.join(words)

149
num2words/lang_DE.py Normal file
View File

@ -0,0 +1,149 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import print_function, unicode_literals
from .lang_EU import Num2Word_EU
class Num2Word_DE(Num2Word_EU):
GIGA_SUFFIX = "illiarde"
MEGA_SUFFIX = "illion"
def setup(self):
self.negword = "minus "
self.pointword = "Komma"
# "Cannot treat float %s as ordinal."
self.errmsg_floatord = (
"Die Gleitkommazahl %s kann nicht in eine Ordnungszahl " +
"konvertiert werden."
)
# "type(((type(%s)) ) not in [long, int, float]"
self.errmsg_nonnum = (
"Nur Zahlen (type(%s)) können in Wörter konvertiert werden."
)
# "Cannot treat negative num %s as ordinal."
self.errmsg_negord = (
"Die negative Zahl %s kann nicht in eine Ordnungszahl " +
"konvertiert werden."
)
# "abs(%s) must be less than %s."
self.errmsg_toobig = "Die Zahl %s muss kleiner als %s sein."
self.exclude_title = []
lows = ["non", "okt", "sept", "sext", "quint", "quadr", "tr", "b", "m"]
units = ["", "un", "duo", "tre", "quattuor", "quin", "sex", "sept",
"okto", "novem"]
tens = ["dez", "vigint", "trigint", "quadragint", "quinquagint",
"sexagint", "septuagint", "oktogint", "nonagint"]
self.high_numwords = (
["zent"] + self.gen_high_numwords(units, tens, lows)
)
self.mid_numwords = [(1000, "tausend"), (100, "hundert"),
(90, "neunzig"), (80, "achtzig"), (70, "siebzig"),
(60, "sechzig"), (50, "f\xFCnfzig"),
(40, "vierzig"), (30, "drei\xDFig")]
self.low_numwords = ["zwanzig", "neunzehn", "achtzehn", "siebzehn",
"sechzehn", "f\xFCnfzehn", "vierzehn", "dreizehn",
"zw\xF6lf", "elf", "zehn", "neun", "acht",
"sieben", "sechs", "f\xFCnf", "vier", "drei",
"zwei", "eins", "null"]
self.ords = {"eins": "ers",
"drei": "drit",
"acht": "ach",
"sieben": "sieb",
"ig": "igs",
"ert": "erts",
"end": "ends",
"ion": "ions",
"nen": "ns",
"rde": "rds",
"rden": "rds"}
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if cnum == 1:
if nnum == 100 or nnum == 1000:
return ("ein" + ntext, nnum)
elif nnum < 10 ** 6:
return next
ctext = "eine"
if nnum > cnum:
if nnum >= 10 ** 6:
if cnum > 1:
if ntext.endswith("e"):
ntext += "n"
else:
ntext += "en"
ctext += " "
val = cnum * nnum
else:
if nnum < 10 < cnum < 100:
if nnum == 1:
ntext = "ein"
ntext, ctext = ctext, ntext + "und"
elif cnum >= 10 ** 6:
ctext += " "
val = cnum + nnum
word = ctext + ntext
return (word, val)
def to_ordinal(self, value):
self.verify_ordinal(value)
outword = self.to_cardinal(value)
for key in self.ords:
if outword.endswith(key):
outword = outword[:len(outword) - len(key)] + self.ords[key]
break
res = outword + "te"
# Exception: "hundertste" is usually preferred over "einhundertste"
if res == "eintausendste" or res == "einhundertste":
res = res.replace("ein", "", 1)
return res
def to_ordinal_num(self, value):
self.verify_ordinal(value)
return str(value) + "."
def to_currency(self, val, longval=True, old=False):
hightxt = "Euro"
lowtxt = "Cent"
if old:
hightxt = "Mark"
lowtxt = "Pfennig/e"
cents = int(round(val*100))
res = self.to_splitnum(cents, hightxt=hightxt, lowtxt=lowtxt,
jointxt="und", longval=longval)
# Handle exception, in german is "ein Euro" and not "eins Euro"
if res.startswith("eins "):
res = res.replace("eins ", "ein ", 1)
return res
def to_year(self, val, longval=True):
if not (val // 100) % 10:
return self.to_cardinal(val)
return self.to_splitnum(val, hightxt="hundert", longval=longval)\
.replace(' ', '')

132
num2words/lang_DK.py Normal file
View File

@ -0,0 +1,132 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import division, print_function, unicode_literals
from . import lang_EU
class Num2Word_DK(lang_EU.Num2Word_EU):
GIGA_SUFFIX = "illarder"
MEGA_SUFFIX = "illioner"
def setup(self):
super(Num2Word_DK, self).setup()
self.negword = "minus "
self.pointword = "komma"
self.exclude_title = ["og", "komma", "minus"]
self.mid_numwords = [(1000, "tusind"), (100, "hundrede"),
(90, "halvfems"), (80, "firs"),
(70, "halvfjerds"), (60, "treds"),
(50, "halvtreds"), (40, "fyrre"), (30, "tredive")]
self.low_numwords = ["tyve", "nitten", "atten", "sytten",
"seksten", "femten", "fjorten", "tretten",
"tolv", "elleve", "ti", "ni", "otte",
"syv", "seks", "fem", "fire", "tre", "to",
"et", "nul"]
self.ords = {"nul": "nul",
"et": "f\xf8rste",
"to": "anden",
"tre": "tredje",
"fire": "fjerde",
"fem": "femte",
"seks": "sjette",
"syv": "syvende",
"otte": "ottende",
"ni": "niende",
"ti": "tiende",
"elleve": "ellevte",
"tolv": "tolvte",
"tretten": "trett",
"fjorten": "fjort",
"femten": "femt",
"seksten": "sekst",
"sytten": "sytt",
"atten": "att",
"nitten": "nitt",
"tyve": "tyv"}
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if next[1] == 100 or next[1] == 1000:
lst = list(next)
lst[0] = 'et' + lst[0]
next = tuple(lst)
if cnum == 1:
if nnum < 10 ** 6 or self.ordflag:
return next
ctext = "en"
if nnum > cnum:
if nnum >= 10 ** 6:
ctext += " "
val = cnum * nnum
else:
if cnum >= 100 and cnum < 1000:
ctext += " og "
elif cnum >= 1000 and cnum <= 100000:
ctext += "e og "
if nnum < 10 < cnum < 100:
if nnum == 1:
ntext = "en"
ntext, ctext = ctext, ntext + "og"
elif cnum >= 10 ** 6:
ctext += " "
val = cnum + nnum
word = ctext + ntext
return (word, val)
def to_ordinal(self, value):
self.verify_ordinal(value)
self.ordflag = True
outword = self.to_cardinal(value)
self.ordflag = False
for key in self.ords:
if outword.endswith(key):
outword = outword[:len(outword) - len(key)] + self.ords[key]
break
if value % 100 >= 30 and value % 100 <= 39 or value % 100 == 0:
outword += "te"
elif value % 100 > 12 or value % 100 == 0:
outword += "ende"
return outword
def to_ordinal_num(self, value):
self.verify_ordinal(value)
vaerdte = (0, 1, 5, 6, 11, 12)
if value % 100 >= 30 and value % 100 <= 39 or value % 100 in vaerdte:
return str(value) + "te"
elif value % 100 == 2:
return str(value) + "en"
return str(value) + "ende"
def to_currency(self, val, longval=True):
if val // 100 == 1 or val == 1:
ret = self.to_splitnum(val, hightxt="kr", lowtxt="\xf8re",
jointxt="og", longval=longval)
return "en " + ret[3:]
return self.to_splitnum(val, hightxt="kr", lowtxt="\xf8re",
jointxt="og", longval=longval)
def to_year(self, val, longval=True):
if val == 1:
return 'en'
if not (val // 100) % 10:
return self.to_cardinal(val)
return self.to_splitnum(val, hightxt="hundrede", longval=longval)

110
num2words/lang_EN.py Normal file
View File

@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import division, print_function, unicode_literals
from . import lang_EU
class Num2Word_EN(lang_EU.Num2Word_EU):
def set_high_numwords(self, high):
max = 3 + 3 * len(high)
for word, n in zip(high, range(max, 3, -3)):
self.cards[10 ** n] = word + "illion"
def setup(self):
super(Num2Word_EN, self).setup()
self.negword = "minus "
self.pointword = "point"
self.exclude_title = ["and", "point", "minus"]
self.mid_numwords = [(1000, "thousand"), (100, "hundred"),
(90, "ninety"), (80, "eighty"), (70, "seventy"),
(60, "sixty"), (50, "fifty"), (40, "forty"),
(30, "thirty")]
self.low_numwords = ["twenty", "nineteen", "eighteen", "seventeen",
"sixteen", "fifteen", "fourteen", "thirteen",
"twelve", "eleven", "ten", "nine", "eight",
"seven", "six", "five", "four", "three", "two",
"one", "zero"]
self.ords = {"one": "first",
"two": "second",
"three": "third",
"four": "fourth",
"five": "fifth",
"six": "sixth",
"seven": "seventh",
"eight": "eighth",
"nine": "ninth",
"ten": "tenth",
"eleven": "eleventh",
"twelve": "twelfth"}
def merge(self, lpair, rpair):
ltext, lnum = lpair
rtext, rnum = rpair
if lnum == 1 and rnum < 100:
return (rtext, rnum)
elif 100 > lnum > rnum:
return ("%s-%s" % (ltext, rtext), lnum + rnum)
elif lnum >= 100 > rnum:
return ("%s and %s" % (ltext, rtext), lnum + rnum)
elif rnum > lnum:
return ("%s %s" % (ltext, rtext), lnum * rnum)
return ("%s, %s" % (ltext, rtext), lnum + rnum)
def to_ordinal(self, value):
self.verify_ordinal(value)
outwords = self.to_cardinal(value).split(" ")
lastwords = outwords[-1].split("-")
lastword = lastwords[-1].lower()
try:
lastword = self.ords[lastword]
except KeyError:
if lastword[-1] == "y":
lastword = lastword[:-1] + "ie"
lastword += "th"
lastwords[-1] = self.title(lastword)
outwords[-1] = "-".join(lastwords)
return " ".join(outwords)
def to_ordinal_num(self, value):
self.verify_ordinal(value)
return "%s%s" % (value, self.to_ordinal(value)[-2:])
def to_year(self, val, suffix=None, longval=True):
if val < 0:
val = abs(val)
suffix = 'BC' if not suffix else suffix
high, low = (val // 100, val % 100)
# If year is 00XX, X00X, or beyond 9999, go cardinal.
if (high == 0
or (high % 10 == 0 and low < 10)
or high >= 100):
valtext = self.to_cardinal(val)
else:
hightext = self.to_cardinal(high)
if low == 0:
lowtext = "hundred"
elif low < 10:
lowtext = "oh-%s" % self.to_cardinal(low)
else:
lowtext = self.to_cardinal(low)
valtext = "%s %s" % (hightext, lowtext)
return (valtext if not suffix
else "%s %s" % (valtext, suffix))

26
num2words/lang_EN_IN.py Normal file
View File

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from .lang_EN import Num2Word_EN
class Num2Word_EN_IN(Num2Word_EN):
def set_high_numwords(self, high):
self.cards[10 ** 7] = "crore"
self.cards[10 ** 5] = "lakh"

177
num2words/lang_ES.py Normal file
View File

@ -0,0 +1,177 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import print_function, unicode_literals
from .lang_EU import Num2Word_EU
class Num2Word_ES(Num2Word_EU):
CURRENCY_FORMS = {
'EUR': (('euro', 'euros'), ('centimo', 'centimos')),
'ESP': (('peseta', 'pesetas'), ('centimo', 'centimos')),
'USD': (('dolar', 'dolares'), ('centavo', 'centavos')),
'PEN': (('sol', 'soles'), ('centimo', 'centimos')),
}
# //CHECK: Is this sufficient??
GIGA_SUFFIX = None
MEGA_SUFFIX = "illón"
def setup(self):
lows = ["cuatr", "tr", "b", "m"]
self.high_numwords = self.gen_high_numwords([], [], lows)
self.negword = "menos "
self.pointword = "punto"
self.errmsg_nonnum = "Solo números pueden ser convertidos a palabras."
self.errmsg_toobig = (
"Numero muy grande para ser convertido a palabras."
)
self.gender_stem = "o"
self.exclude_title = ["y", "menos", "punto"]
self.mid_numwords = [(1000, "mil"), (100, "cien"), (90, "noventa"),
(80, "ochenta"), (70, "setenta"), (60, "sesenta"),
(50, "cincuenta"), (40, "cuarenta"),
(30, "treinta")]
self.low_numwords = ["veintinueve", "veintiocho", "veintisiete",
"veintiséis", "veinticinco", "veinticuatro",
"veintitrés", "veintidós", "veintiuno",
"veinte", "diecinueve", "dieciocho", "diecisiete",
"dieciseis", "quince", "catorce", "trece", "doce",
"once", "diez", "nueve", "ocho", "siete", "seis",
"cinco", "cuatro", "tres", "dos", "uno", "cero"]
self.ords = {1: "primer",
2: "segund",
3: "tercer",
4: "cuart",
5: "quint",
6: "sext",
7: "séptim",
8: "octav",
9: "noven",
10: "décim",
20: "vigésim",
30: "trigésim",
40: "quadragésim",
50: "quincuagésim",
60: "sexagésim",
70: "septuagésim",
80: "octogésim",
90: "nonagésim",
100: "centésim",
200: "ducentésim",
300: "tricentésim",
400: "cuadrigentésim",
500: "quingentésim",
600: "sexcentésim",
700: "septigentésim",
800: "octigentésim",
900: "noningentésim",
1e3: "milésim",
1e6: "millonésim",
1e9: "billonésim",
1e12: "trillonésim",
1e15: "cuadrillonésim"}
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if cnum == 1:
if nnum < 1000000:
return next
ctext = "un"
elif cnum == 100 and not nnum % 1000 == 0:
ctext += "t" + self.gender_stem
if nnum < cnum:
if cnum < 100:
return "%s y %s" % (ctext, ntext), cnum + nnum
return "%s %s" % (ctext, ntext), cnum + nnum
elif (not nnum % 1000000) and cnum > 1:
ntext = ntext[:-3] + "lones"
if nnum == 100:
if cnum == 5:
ctext = "quinien"
ntext = ""
elif cnum == 7:
ctext = "sete"
elif cnum == 9:
ctext = "nove"
ntext += "t" + self.gender_stem + "s"
else:
ntext = " " + ntext
return (ctext + ntext, cnum * nnum)
def to_ordinal(self, value):
self.verify_ordinal(value)
try:
if value == 0:
text = ""
elif value <= 10:
text = "%s%s" % (self.ords[value], self.gender_stem)
elif value <= 12:
text = (
"%s%s%s" % (self.ords[10], self.gender_stem,
self.to_ordinal(value - 10))
)
elif value <= 100:
dec = (value // 10) * 10
text = (
"%s%s %s" % (self.ords[dec], self.gender_stem,
self.to_ordinal(value - dec))
)
elif value <= 1e3:
cen = (value // 100) * 100
text = (
"%s%s %s" % (self.ords[cen], self.gender_stem,
self.to_ordinal(value - cen))
)
elif value < 1e18:
# dec contains the following:
# [ 1e3, 1e6): 1e3
# [ 1e6, 1e9): 1e6
# [ 1e9, 1e12): 1e9
# [1e12, 1e15): 1e12
# [1e15, 1e18): 1e15
dec = 10 ** ((((len(str(int(value))) - 1) / 3 - 1) + 1) * 3)
part = int(float(value / dec) * dec)
cardinal = (
self.to_cardinal(part / dec) if part / dec != 1 else ""
)
text = (
"%s%s%s %s" % (cardinal, self.ords[dec], self.gender_stem,
self.to_ordinal(value - part))
)
else:
text = self.to_cardinal(value)
except KeyError:
text = self.to_cardinal(value)
return text.strip()
def to_ordinal_num(self, value):
self.verify_ordinal(value)
return "%s%s" % (value, "º" if self.gender_stem == 'o' else "ª")
def to_currency(self, val, currency='EUR', cents=True, seperator=' con',
adjective=False):
result = super(Num2Word_ES, self).to_currency(
val, currency=currency, cents=cents, seperator=seperator,
adjective=adjective)
# Handle exception, in spanish is "un euro" and not "uno euro"
return result.replace("uno", "un")

29
num2words/lang_ES_CO.py Normal file
View File

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import print_function, unicode_literals
from .lang_ES import Num2Word_ES
class Num2Word_ES_CO(Num2Word_ES):
def to_currency(self, val, longval=True, old=False):
result = self.to_splitnum(val, hightxt="peso/s", lowtxt="centavo/s",
divisor=1, jointxt="y", longval=longval)
# Handle exception, in spanish is "un euro" and not "uno euro"
return result.replace("uno", "un")

32
num2words/lang_ES_VE.py Normal file
View File

@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import print_function, unicode_literals
from .lang_ES import Num2Word_ES
class Num2Word_ES_VE(Num2Word_ES):
def to_currency(self, val, longval=True, old=False):
hightxt = "bolívar/es" if old else "bolívar/es fuerte/s"
result = self.to_splitnum(
val, hightxt=hightxt, lowtxt="centavo/s",
divisor=1, jointxt="y", longval=longval
)
# Handle exception, in spanish is "un euro" and not "uno euro"
return result.replace("uno", "un")

87
num2words/lang_EU.py Normal file
View File

@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from .base import Num2Word_Base
GENERIC_DOLLARS = ('dollar', 'dollars')
GENERIC_CENTS = ('cent', 'cents')
class Num2Word_EU(Num2Word_Base):
CURRENCY_FORMS = {
'AUD': (GENERIC_DOLLARS, GENERIC_CENTS),
'CAD': (GENERIC_DOLLARS, GENERIC_CENTS),
# repalced by EUR
'EEK': (('kroon', 'kroons'), ('sent', 'senti')),
'EUR': (('euro', 'euro'), GENERIC_CENTS),
'GBP': (('pound sterling', 'pounds sterling'), ('penny', 'pence')),
# replaced by EUR
'LTL': (('litas', 'litas'), GENERIC_CENTS),
# replaced by EUR
'LVL': (('lat', 'lats'), ('santim', 'santims')),
'USD': (GENERIC_DOLLARS, GENERIC_CENTS),
'RUB': (('rouble', 'roubles'), ('kopek', 'kopeks')),
'SEK': (('krona', 'kronor'), ('öre', 'öre')),
'NOK': (('krone', 'kroner'), ('øre', 'øre')),
'PLN': (('zloty', 'zlotys', 'zlotu'), ('grosz', 'groszy')),
'MXN': (('peso', 'pesos'), GENERIC_CENTS),
'RON': (('leu', 'lei'), ('ban', 'bani')),
}
CURRENCY_ADJECTIVES = {
'AUD': 'Australian',
'CAD': 'Canadian',
'EEK': 'Estonian',
'USD': 'US',
'RUB': 'Russian',
'NOK': 'Norwegian',
'MXN': 'Mexican',
'RON': 'Romanian',
}
GIGA_SUFFIX = "illiard"
MEGA_SUFFIX = "illion"
def set_high_numwords(self, high):
cap = 3 + 6 * len(high)
for word, n in zip(high, range(cap, 3, -6)):
if self.GIGA_SUFFIX:
self.cards[10 ** n] = word + self.GIGA_SUFFIX
if self.MEGA_SUFFIX:
self.cards[10 ** (n - 3)] = word + self.MEGA_SUFFIX
def gen_high_numwords(self, units, tens, lows):
out = [u + t for t in tens for u in units]
out.reverse()
return out + lows
def pluralize(self, n, forms):
form = 0 if n == 1 else 1
return forms[form]
def setup(self):
lows = ["non", "oct", "sept", "sext", "quint", "quadr", "tr", "b", "m"]
units = ["", "un", "duo", "tre", "quattuor", "quin", "sex", "sept",
"octo", "novem"]
tens = ["dec", "vigint", "trigint", "quadragint", "quinquagint",
"sexagint", "septuagint", "octogint", "nonagint"]
self.high_numwords = ["cent"] + self.gen_high_numwords(units, tens,
lows)

736
num2words/lang_FI.py Normal file
View File

@ -0,0 +1,736 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import division, print_function, unicode_literals
from collections import OrderedDict
from . import lang_EU
GENERIC_CENTS = ('sentti', 'senttiä')
GENERIC_CENTAVOS = ('centavo', 'centavoa')
# grammatical cases
NOM = 10 # nominative: the dictionary form
GEN = 11 # genitive: ~of/'s
ACC = 12 # accusative: not used; either nominative or genitive
PTV = 13 # partitive: as an object
# locative cases (internal)
INE = 14 # inessive: in
ELA = 15 # elative: from/out of
ILL = 16 # illative: into
# locative cases (external)
ADE = 17 # adessive: at/on
ABL = 18 # ablative: from (after being at/on, not in)
ALL = 19 # allative: to
# essive
ESS = 20 # essive: as (in the role of)
TRANSL = 21 # translative: to (the role of; being sth)
# rare
INSTRUC = 22 # instructive: with (plural is the same as singular)
ABE = 23 # abessive: without
COM = 24 # comitative: together with (plural = singular)
NAME_TO_CASE = {
'nominative': NOM,
'genitive': GEN,
'accusative': ACC,
'partitive': PTV,
'inessive': INE,
'elative': ELA,
'illative': ILL,
'adessive': ADE,
'ablative': ABL,
'allative': ALL,
'essive': ESS,
'translative': TRANSL,
'instructive': INSTRUC,
'abessive': ABE,
'comitative': COM,
}
# https://en.wikibooks.org/wiki/Finnish/Grammar-Vowel_harmony
BACK_TO_FRONT = {
'a': 'ä',
'o': 'ö',
'u': 'y',
}
# https://en.wiktionary.org/wiki/Appendix:Finnish_nominal_inflection
# CASE: (SINGULAR_SUFFIX+, PLURAL_SUFFIX+)
KOTUS_TYPE = {
# Kotus type 5/risti, no gradation
5: {
# grammatical
NOM: ('i', 'it'),
GEN: ('in', 'ien'),
PTV: ('ia', 'eja'),
# locative, internal
INE: ('issa', 'eissa'),
ELA: ('ista', 'eista'),
ILL: ('iin', 'eihin'),
# locative, external
ADE: ('illa', 'eilla'),
ABL: ('ilta', 'eilta'),
ALL: ('ille', 'eille'),
# essive
ESS: ('ina', 'eina'),
TRANSL: ('iksi', 'eiksi'),
# rare
INSTRUC: ('ein', 'ein'),
ABE: ('itta', 'eitta'),
COM: ('eine', 'eine'), # works better
},
# Kotus type 7/ovi, no gradation
7: {
# grammatical
NOM: ('i', 'et'),
GEN: ('en', 'ien'),
PTV: ('ea', 'ia'),
# locative, internal
INE: ('essa', 'issa'),
ELA: ('esta', 'ista'),
ILL: ('een', 'iin'),
# locative, external
ADE: ('ella', 'illa'),
ABL: ('elta', 'ilta'),
ALL: ('elle', 'ille'),
# essive
ESS: ('ena', 'ina'),
TRANSL: ('eksi', 'iksi'),
# rare
INSTRUC: ('in', 'in'),
ABE: ('etta', 'itta'),
COM: ('ine', 'ine'), # works better
},
# Kotus type 8/nalle, no gradation
8: {
# grammatical
NOM: ('e', 'et'),
GEN: ('en', ('ejen', 'ein')),
PTV: ('ea', 'eja'),
# locative, internal
INE: ('essa', 'eissa'),
ELA: ('esta', 'eista'),
ILL: ('een', 'eihin'),
# locative, external
ADE: ('ella', 'eilla'),
ABL: ('elta', 'eilta'),
ALL: ('elle', 'eille'),
# essive
ESS: ('ena', 'eina'),
TRANSL: ('eksi', 'eiksi'),
# rare
INSTRUC: ('ein', 'ein'),
ABE: ('etta', 'eitta'),
COM: ('eine', 'eine'), # works better
},
# Kotus type 9/kala, t-d gradation (sata)
109: {
# grammatical
NOM: ('ta', 'dat'),
GEN: ('dan', ('tojen', 'tain')),
PTV: ('taa', 'toja'),
# locative, internal
INE: ('dassa', 'doissa'),
ELA: ('dasta', 'doista'),
ILL: ('taan', 'toihin'),
# locative, external
ADE: ('dalla', 'doilla'),
ABL: ('dalta', 'doilta'),
ALL: ('dalle', 'doille'),
# essive
ESS: ('tana', 'toina'),
TRANSL: ('daksi', 'doiksi'),
# rare
INSTRUC: ('doin', 'doin'),
ABE: ('datta', 'doitta'),
COM: ('toine', 'toine'), # works better
},
# Kotus type 10/koira, no gradation
10: {
# grammatical
NOM: ('a', 'at'),
GEN: ('an', ('ien', 'ain')),
PTV: ('aa', 'ia'),
# locative, internal
INE: ('assa', 'issa'),
ELA: ('asta', 'ista'),
ILL: ('aan', 'iin'),
# locative, external
ADE: ('alla', 'illa'),
ABL: ('alta', 'ilta'),
ALL: ('alle', 'ille'),
# essive
ESS: ('ana', 'ina'),
TRANSL: ('aksi', 'iksi'),
# rare
INSTRUC: ('in', 'in'),
ABE: ('atta', 'itta'),
COM: ('ine', 'ine'), # works better
},
# Kotus type 27/käsi, t-d gradation
27: {
# grammatical
NOM: ('si', 'det'),
GEN: ('den', ('sien', 'tten')),
PTV: ('tta', 'sia'),
# locative, internal
INE: ('dessa', 'sissa'),
ELA: ('desta', 'sista'),
ILL: ('teen', 'siin'),
# locative, external
ADE: ('della', 'silla'),
ABL: ('delta', 'silta'),
ALL: ('delle', 'sille'),
# essive
ESS: ('tena', 'sina'),
TRANSL: ('deksi', 'siksi'),
# rare
INSTRUC: ('sin', 'sin'),
ABE: ('detta', 'sitta'),
COM: ('sine', 'sine'), # works better
},
# Kotus type 31/kaksi, t-d gradation
31: {
# grammatical
NOM: ('ksi', 'hdet'),
GEN: ('hden', 'ksien'),
PTV: ('hta', 'ksia'),
# locative, internal
INE: ('hdessa', 'ksissa'),
ELA: ('hdesta', 'ksista'),
ILL: ('hteen', 'ksiin'),
# locative, external
ADE: ('hdella', 'ksilla'),
ABL: ('hdelta', 'ksilta'),
ALL: ('hdelle', 'ksille'),
# essive
ESS: ('htena', 'ksina'),
TRANSL: ('hdeksi', 'ksiksi'),
# rare
INSTRUC: ('ksin', 'ksin'),
ABE: ('hdetta', 'ksitta'),
COM: ('ksine', 'ksine'), # works better
},
# Kotus type 32/sisar, no gradation
32: {
# grammatical
NOM: ('', 'et'),
GEN: ('en', ('ien', 'ten')),
PTV: ('ta', 'ia'),
# locative, internal
INE: ('essa', 'issa'),
ELA: ('esta', 'ista'),
ILL: ('een', 'iin'),
# locative, external
ADE: ('ella', 'illa'),
ABL: ('elta', 'ilta'),
ALL: ('elle', 'ille'),
# essive
ESS: ('ena', 'ina'),
TRANSL: ('eksi', 'iksi'),
# rare
INSTRUC: ('in', 'in'),
ABE: ('etta', 'itta'),
COM: ('ine', 'ine'), # works better
},
# Kotus type 38/nainen, no gradation
38: {
# grammatical
NOM: ('nen', 'set'),
GEN: ('sen', ('sten', 'sien')),
PTV: ('sta', 'sia'),
# locative, internal
INE: ('sessa', 'sissa'),
ELA: ('sesta', 'sista'),
ILL: ('seen', 'siin'),
# locative, external
ADE: ('sella', 'silla'),
ABL: ('selta', 'silta'),
ALL: ('selle', 'sille'),
# essive
ESS: ('sena', 'sina'),
TRANSL: ('seksi', 'siksi'),
# rare
INSTRUC: ('sin', 'sin'),
ABE: ('setta', 'sitta'),
COM: ('sine', 'sine'), # works better
},
# Kotus type 45/kahdeksas, nt-nn gradation
45: {
# grammatical
NOM: ('s', 'nnet'),
GEN: ('nnen', 'nsien'),
PTV: ('tta', 'nsia'),
# locative, internal
INE: ('nnessa', 'nsissa'),
ELA: ('nnesta', 'nsista'),
ILL: ('nteen', 'nsiin'),
# locative, external
ADE: ('nnella', 'nsilla'),
ABL: ('nnelta', 'nsilta'),
ALL: ('nnelle', 'nsille'),
# essive
ESS: ('ntena', 'nsina'),
TRANSL: ('nneksi', 'nsiksi'),
# rare
INSTRUC: ('nsin', 'nsin'),
ABE: ('nnetta', 'nsitta'),
COM: ('nsine', 'nsine'), # works better
},
# Kotus type 46/tuhat, nt-nn gradation
46: {
# grammatical
NOM: ('t', 'nnet'),
GEN: ('nnen', ('nsien', 'nten')),
PTV: ('tta', 'nsia'),
# locative, internal
INE: ('nnessa', 'nsissa'),
ELA: ('nnesta', 'nsista'),
ILL: ('nteen', 'nsiin'),
# locative, external
ADE: ('nnella', 'nsilla'),
ABL: ('nnelta', 'nsilta'),
ALL: ('nnelle', 'nsille'),
# essive
ESS: ('ntena', 'nsina'),
TRANSL: ('nneksi', 'nsiksi'),
# rare
INSTRUC: ('nsin', 'nsin'),
ABE: ('nnetta', 'nsitta'),
COM: ('nsine', 'nsine'), # works better
},
}
# kolme
KOTUS_TYPE[108] = {
c: (KOTUS_TYPE[8][c][0], KOTUS_TYPE[7][c][1])
for c in KOTUS_TYPE[8]
}
KOTUS_TYPE[108][INSTRUC] = ('en', 'in')
KOTUS_TYPE[108][ABE] = ('etta', 'itta')
KOTUS_TYPE[108][COM] = ('ine', 'ine')
# seitsemän, kahdeksan, yhdeksän
KOTUS_TYPE[110] = KOTUS_TYPE[10].copy()
KOTUS_TYPE[110][NOM] = ('an', 'at')
# kymmenen
KOTUS_TYPE[132] = KOTUS_TYPE[32].copy()
KOTUS_TYPE[132][NOM] = ('en', 'et')
def inflect(parts, options):
if not isinstance(parts, list):
parts = [parts]
out = ''
for part in parts:
# part is plain text, concat and continue
if not isinstance(part, tuple):
out += part
continue
# predefined case (kaksikymmentä, ...)
tmp_case = options.case
if len(part) == 3:
# override singular nominative only
if options.case == NOM and not options.plural:
tmp_case = part[2]
part = part[:2]
# stem and suffix
stem, kotus_type = part
suffix = KOTUS_TYPE[kotus_type][tmp_case][options.plural]
# many choices, choose preferred or first
if isinstance(suffix, tuple):
common = set(suffix) & set(options.prefer or set())
if len(common) == 1:
suffix = common.pop()
else:
suffix = suffix[0]
# apply vowel harmony
if not set(BACK_TO_FRONT) & set(stem):
for back, front in BACK_TO_FRONT.items():
suffix = suffix.replace(back, front)
# concat
out += stem + suffix
return out
class Options(object):
def __init__(self, ordinal, case, plural, prefer):
self.ordinal = ordinal
self.case = case
self.plural = plural
self.prefer = prefer
def variation(self, ordinal=None, case=None, plural=None, prefer=None):
return Options(
ordinal if ordinal is not None else self.ordinal,
case if case is not None else self.case,
plural if plural is not None else self.plural,
prefer if prefer is not None else self.prefer,
)
class Num2Word_FI(lang_EU.Num2Word_EU):
CURRENCY_FORMS = {
'BRL': (('real', 'realia'), GENERIC_CENTAVOS),
'CHF': (('frangi', 'frangia'), ('rappen', 'rappenia')),
'CNY': (('juan', 'juania'), ('fen', 'feniä')),
'EUR': (('euro', 'euroa'), GENERIC_CENTS),
'FIM': (('markka', 'markkaa'), ('penni', 'penniä')), # historical
'INR': (('rupia', 'rupiaa'), ('paisa', 'paisaa')),
'JPY': (('jeni', 'jeniä'), ('sen', 'seniä')), # rare subunit
'KRW': (('won', 'wonia'), ('jeon', 'jeonia')), # rare subunit
'KPW': (('won', 'wonia'), ('chon', 'chonia')), # rare subunit
'MXN': (('peso', 'pesoa'), GENERIC_CENTAVOS),
'RUB': (('rupla', 'ruplaa'), ('kopeekka', 'kopeekkaa')),
'TRY': (('liira', 'liiraa'), ('kuruş', 'kuruşia')),
'ZAR': (('randi', 'randia'), GENERIC_CENTS),
}
# crowns
for curr_code in 'DKK', 'ISK', 'NOK', 'SEK':
CURRENCY_FORMS[curr_code] = (('kruunu', 'kruunua'), ('äyri', 'äyriä'))
# dollars
for curr_code in 'AUD', 'CAD', 'HKD', 'NZD', 'SGD', 'USD':
CURRENCY_FORMS[curr_code] = (
('dollari', 'dollaria'), GENERIC_CENTS)
# pounds
for curr_code in ('GBP',):
CURRENCY_FORMS[curr_code] = (('punta', 'puntaa'), ('penny', 'pennyä'))
CURRENCY_ADJECTIVES = {
'AUD': 'Australian',
'BRL': 'Brasilian',
'CAD': 'Kanadan',
'CHF': 'Sveitsin',
'DKK': 'Tanskan',
'FIM': 'Suomen', # historical
'GBP': 'Englannin',
'HKD': 'Hongkongin',
'INR': 'Intian',
'ISK': 'Islannin',
'KRW': 'Etelä-Korean',
'KPW': 'Pohjois-Korean',
'MXN': 'Meksikon',
'NOK': 'Norjan',
'NZD': 'Uuden-Seelannin',
'RUB': 'Venäjän',
'SEK': 'Ruotsin',
'SGD': 'Singaporen',
'TRY': 'Turkin',
'USD': 'Yhdysvaltain',
'ZAR': 'Etelä-Afrikan',
}
def __init__(self):
self.ords = OrderedDict()
super(Num2Word_FI, self).__init__()
def set_numwords(self):
self.set_high_numwords(self.high_numwords)
self.set_mid_numwords(self.mid_numwords, self.mid_ords)
self.set_low_numwords(self.low_numwords, self.low_ords)
def set_high_numwords(self, high):
# references:
# https://fi.wikipedia.org/wiki/Suurten_lukujen_nimet
# https://en.wikipedia.org/wiki/Names_of_large_numbers#Standard_dictionary_numbers
# translate to Finnish
replacements = [
("qu", "kv"),
("x", "ks"),
("c", "k"),
("kent", "sent"), # applied after c -> k to cent
]
translated = []
for i, numword in enumerate(high):
# notes:
# - 1e6**9 can be either noviljoona or noniljoona
# - 1e6**38 and above are untested
# 1e6**6 is sekstiljoona but 1e6**16 is sedekiljoona
if numword.startswith("sex") and numword != "sext":
numword = numword.replace("sex", "se")
# 1e6**7 is septiljoona but 1e6**17 is septendekiljoona
elif numword.startswith("sept") and numword != "sept":
numword = "septen" + numword[len("sept"):]
# 1e6**8 is oktiljoona but 1e6**18 is duodevigintiljoona
# (2 from 20)
elif numword.startswith("octo"):
numword = high[i + -10]
numword = "duode" + numword[len("octo"):]
# 1e6**9 is noniljoona but 1e6**19 is undevigintiljoona (1 from 20)
elif numword.startswith("nove"):
numword = high[i + -10]
numword = "unde" + numword[len("nove") + 1:]
# apply general replacements to all numwords
for repl in replacements:
numword = numword.replace(repl[0], repl[1])
translated.append(numword)
max = 6 * len(translated)
for word, n in zip(translated, range(max, 0, -6)):
if n == 6:
# irregularity considering short scale and long scale
self.cards[10 ** 9] = ("miljard", 5)
self.ords[10 ** 9] = ("miljardi", 45)
self.cards[10 ** n] = (word + "iljoon", 10)
self.ords[10 ** n] = (word + "iljoona", 45)
def set_mid_numwords(self, cards, ords):
for key, val in cards:
self.cards[key] = val
for key, val in ords:
self.ords[key] = val
def set_low_numwords(self, cards, ords):
for key, val in cards:
self.cards[key] = val
for key, val in ords:
self.ords[key] = val
def setup(self):
super(Num2Word_FI, self).setup()
self.negword = "miinus "
self.pointword = "pilkku"
self.exclude_title = ["pilkku", "miinus"]
self.mid_numwords = [
(1000, ("tuha", 46)),
(100, ("sa", 109)),
(90, [("yhdeks", 110), ("kymmen", 132, PTV)]),
(80, [("kahdeks", 110), ("kymmen", 132, PTV)]),
(70, [("seitsem", 110), ("kymmen", 132, PTV)]),
(60, [("kuu", 27), ("kymmen", 132, PTV)]),
(50, [("vii", 27), ("kymmen", 132, PTV)]),
(40, [("nelj", 10), ("kymmen", 132, PTV)]),
(30, [("kolm", 108), ("kymmen", 132, PTV)]),
]
self.mid_ords = [
(1000, ("tuhanne", 45)),
(100, ("sada", 45)),
(90, [("yhdeksä", 45), ("kymmene", 45)]),
(80, [("kahdeksa", 45), ("kymmene", 45)]),
(70, [("seitsemä", 45), ("kymmene", 45)]),
(60, [("kuude", 45), ("kymmene", 45)]),
(50, [("viide", 45), ("kymmene", 45)]),
(40, [("neljä", 45), ("kymmene", 45)]),
(30, [("kolma", 45), ("kymmene", 45)]),
]
self.low_numwords = [
(20, [("ka", 31), ("kymmen", 132, PTV)]),
(19, [("yhdeks", 110), "toista"]),
(18, [("kahdeks", 110), "toista"]),
(17, [("seitsem", 110), "toista"]),
(16, [("kuu", 27), "toista"]),
(15, [("vii", 27), "toista"]),
(14, [("nelj", 10), "toista"]),
(13, [("kolm", 108), "toista"]),
(12, [("ka", 31), "toista"]),
(11, [("y", 31), "toista"]),
(10, ("kymmen", 132)),
(9, ("yhdeks", 110)),
(8, ("kahdeks", 110)),
(7, ("seitsem", 110)),
(6, ("kuu", 27)),
(5, ("vii", 27)),
(4, ("nelj", 10)),
(3, ("kolm", 108)),
(2, ("ka", 31)),
(1, ("y", 31)),
(0, ("noll", 10)),
]
self.low_ords = [
(20, [("kahde", 45), ("kymmene", 45)]),
(19, [("yhdeksä", 45), "toista"]),
(18, [("kahdeksa", 45), "toista"]),
(17, [("seitsemä", 45), "toista"]),
(16, [("kuude", 45), "toista"]),
(15, [("viide", 45), "toista"]),
(14, [("neljä", 45), "toista"]),
(13, [("kolma", 45), "toista"]),
(12, [("kahde", 45), "toista"]),
(11, [("yhde", 45), "toista"]),
(10, ("kymmene", 45)),
(9, ("yhdeksä", 45)),
(8, ("kahdeksa", 45)),
(7, ("seitsemä", 45)),
(6, ("kuude", 45)),
(5, ("viide", 45)),
(4, ("neljä", 45)),
(3, ("kolma", 45)),
(2, ("toi", 38)),
(1, ("ensimmäi", 38)),
(0, ("nolla", 45)),
]
def merge(self, lpair, rpair, options):
ltext, lnum = lpair
rtext, rnum = rpair
# http://www.kielitoimistonohjepankki.fi/ohje/49
fmt = "%s%s"
# ignore lpair if lnum is 1
if lnum == 1:
rtext = inflect(rtext, options)
return (rtext, rnum)
# rnum is added to lnum
elif lnum > rnum:
ltext = inflect(ltext, options)
rtext = inflect(rtext, options)
# separate groups with space
if lnum >= 1000:
fmt = "%s %s"
return (fmt % (ltext, rtext), lnum + rnum)
# rnum is multiplied by lnum
elif lnum < rnum:
if options.ordinal:
# kahdessadas, not toinensadas
if lnum == 2:
ltext = ("kahde", 45)
rtext = inflect(rtext, options)
else:
# kaksituhatta but kahdettuhannet
rcase = options.case
if options.case == NOM and not options.plural:
rcase = PTV
rtext = inflect(rtext, options.variation(case=rcase))
ltext = inflect(ltext, options)
return (fmt % (ltext, rtext), lnum * rnum)
def to_cardinal(self, value, case='nominative', plural=False, prefer=None):
case = NAME_TO_CASE[case]
options = Options(False, case, plural, prefer)
try:
assert int(value) == value
except (ValueError, TypeError, AssertionError):
if case != NOM:
raise NotImplementedError(
"Cases other than nominative are not implemented for "
"cardinal floating point numbers.")
return self.to_cardinal_float(value)
out = ""
if value < 0:
value = abs(value)
out = self.negword
if value >= self.MAXVAL:
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
val = self.splitnum(value, options)
words, num = self.clean(val, options)
return self.title(out + words)
def to_ordinal(self, value, case='nominative', plural=False, prefer=None):
case = NAME_TO_CASE[case]
options = Options(True, case, plural, prefer)
self.verify_ordinal(value)
if value >= self.MAXVAL:
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
val = self.splitnum(value, options)
words, num = self.clean(val, options)
return self.title(words)
def to_ordinal_num(self, value, case='nominative', plural=False):
case = NAME_TO_CASE[case]
raise NotImplementedError
def to_year(self, val, suffix=None, longval=True):
suffix = suffix or ""
if val < 0:
val = abs(val)
suffix = suffix or " ennen ajanlaskun alkua"
return self.to_cardinal(val).replace(" ", "") + suffix
def to_currency(self, val, currency="EUR", cents=True, seperator=" ja",
adjective=False):
return super(Num2Word_FI, self).to_currency(
val, currency=currency, cents=cents, seperator=seperator,
adjective=adjective)
def splitnum(self, value, options):
elems = self.ords if options.ordinal else self.cards
for elem in elems:
if elem > value:
continue
out = []
if value == 0:
div, mod = 1, 0
else:
div, mod = divmod(value, elem)
if div == 1:
out.append((elems[1], 1))
else:
if div == value: # The system tallies, eg Roman Numerals
return [(div * elems[elem], div*elem)]
out.append(self.splitnum(div, options))
out.append((elems[elem], elem))
if mod:
out.append(self.splitnum(mod, options))
return out
def clean(self, val, options):
out = val
while len(val) != 1:
out = []
left, right = val[:2]
if isinstance(left, tuple) and isinstance(right, tuple):
out.append(self.merge(left, right, options))
if val[2:]:
out.append(val[2:])
else:
for elem in val:
if isinstance(elem, list):
if len(elem) == 1:
out.append(elem[0])
else:
out.append(self.clean(elem, options))
else:
out.append(elem)
val = out
return out[0]

101
num2words/lang_FR.py Normal file
View File

@ -0,0 +1,101 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import print_function, unicode_literals
from .lang_EU import Num2Word_EU
class Num2Word_FR(Num2Word_EU):
def setup(self):
Num2Word_EU.setup(self)
self.negword = "moins "
self.pointword = "virgule"
self.errmsg_nonnum = (
u"Seulement des nombres peuvent être convertis en mots."
)
self.errmsg_toobig = u"Nombre trop grand pour être converti en mots."
self.exclude_title = ["et", "virgule", "moins"]
self.mid_numwords = [(1000, "mille"), (100, "cent"),
(80, "quatre-vingts"), (60, "soixante"),
(50, "cinquante"), (40, "quarante"),
(30, "trente")]
self.low_numwords = ["vingt", "dix-neuf", "dix-huit", "dix-sept",
"seize", "quinze", "quatorze", "treize", "douze",
"onze", "dix", "neuf", "huit", "sept", "six",
"cinq", "quatre", "trois", "deux", "un", "zéro"]
self.ords = {
"cinq": "cinquième",
"neuf": "neuvième",
}
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if cnum == 1:
if nnum < 1000000:
return next
else:
if (not (cnum - 80) % 100
or (not cnum % 100 and cnum < 1000))\
and nnum < 1000000 \
and ctext[-1] == "s":
ctext = ctext[:-1]
if cnum < 1000 and nnum != 1000 and \
ntext[-1] != "s" and not nnum % 100:
ntext += "s"
if nnum < cnum < 100:
if nnum % 10 == 1 and cnum != 80:
return ("%s et %s" % (ctext, ntext), cnum + nnum)
return ("%s-%s" % (ctext, ntext), cnum + nnum)
if nnum > cnum:
return ("%s %s" % (ctext, ntext), cnum * nnum)
return ("%s %s" % (ctext, ntext), cnum + nnum)
# Is this right for such things as 1001 - "mille unième" instead of
# "mille premier"?? "millième"??
def to_ordinal(self, value):
self.verify_ordinal(value)
if value == 1:
return "premier"
word = self.to_cardinal(value)
for src, repl in self.ords.items():
if word.endswith(src):
word = word[:-len(src)] + repl
break
else:
if word[-1] == "e":
word = word[:-1]
word = word + "ième"
return word
def to_ordinal_num(self, value):
self.verify_ordinal(value)
out = str(value)
out += {"1": "er"}.get(out[-1], "me")
return out
def to_currency(self, val, longval=True, old=False):
hightxt = "euro/s"
if old:
hightxt = "franc/s"
cents = int(round(val*100))
return self.to_splitnum(cents, hightxt=hightxt, lowtxt="centime/s",
divisor=100, jointxt="et", longval=longval)

49
num2words/lang_FR_BE.py Normal file
View File

@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import print_function, unicode_literals
from .lang_FR import Num2Word_FR
class Num2Word_FR_BE(Num2Word_FR):
def setup(self):
Num2Word_FR.setup(self)
self.mid_numwords = [(1000, "mille"), (100, "cent"), (90, "nonante"),
(80, "quatre-vingt"), (70, "septante"),
(60, "soixante"), (50, "cinquante"),
(40, "quarante"), (30, "trente")]
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if cnum == 1:
if nnum < 1000000:
return next
if cnum < 1000 and nnum != 1000 and\
ntext[-1] != "s" and not nnum % 100:
ntext += "s"
if nnum < cnum < 100:
if nnum % 10 == 1:
return ("%s et %s" % (ctext, ntext), cnum + nnum)
return ("%s-%s" % (ctext, ntext), cnum + nnum)
if nnum > cnum:
return ("%s %s" % (ctext, ntext), cnum * nnum)
return ("%s %s" % (ctext, ntext), cnum + nnum)

48
num2words/lang_FR_CH.py Normal file
View File

@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import print_function, unicode_literals
from .lang_FR import Num2Word_FR
class Num2Word_FR_CH(Num2Word_FR):
def setup(self):
Num2Word_FR.setup(self)
self.mid_numwords = [(1000, "mille"), (100, "cent"), (90, "nonante"),
(80, "huitante"), (70, "septante"),
(60, "soixante"), (50, "cinquante"),
(40, "quarante"), (30, "trente")]
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if cnum == 1:
if nnum < 1000000:
return next
if cnum < 1000 and nnum != 1000 and\
ntext[-1] != "s" and not nnum % 100:
ntext += "s"
if nnum < cnum < 100:
if nnum % 10 == 1:
return ("%s et %s" % (ctext, ntext), cnum + nnum)
return ("%s-%s" % (ctext, ntext), cnum + nnum)
if nnum > cnum:
return ("%s %s" % (ctext, ntext), cnum * nnum)
return ("%s %s" % (ctext, ntext), cnum + nnum)

28
num2words/lang_FR_DZ.py Normal file
View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from .lang_FR import Num2Word_FR
class Num2Word_FR_DZ(Num2Word_FR):
def to_currency(self, val, longval=True, cents=True, jointxt="virgule"):
return self.to_splitnum(
val, hightxt="dinard/s", lowtxt="centime/s", divisor=1,
jointxt=jointxt, longval=longval, cents=cents
)

150
num2words/lang_HE.py Normal file
View File

@ -0,0 +1,150 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import print_function, unicode_literals
from .utils import get_digits, splitbyx
ZERO = (u'אפס',)
ONES = {
1: (u'אחד',),
2: (u'שנים',),
3: (u'שלש',),
4: (u'ארבע',),
5: (u'חמש',),
6: (u'שש',),
7: (u'שבע',),
8: (u'שמנה',),
9: (u'תשע',),
}
TENS = {
0: (u'עשר',),
1: (u'אחד עשרה',),
2: (u'שנים עשרה',),
3: (u'שלש עשרה',),
4: (u'ארבע עשרה',),
5: (u'חמש עשרה',),
6: (u'שש עשרה',),
7: (u'שבע עשרה',),
8: (u'שמנה עשרה',),
9: (u'תשע עשרה',),
}
TWENTIES = {
2: (u'עשרים',),
3: (u'שלשים',),
4: (u'ארבעים',),
5: (u'חמישים',),
6: (u'ששים',),
7: (u'שבעים',),
8: (u'שמנים',),
9: (u'תשעים',),
}
HUNDRED = {
1: (u'מאה',),
2: (u'מאתיים',),
3: (u'מאות',)
}
THOUSANDS = {
1: (u'אלף',),
2: (u'אלפיים',),
}
AND = u'ו'
def pluralize(n, forms):
# gettext implementation:
# (n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2)
form = 0 if (n % 10 == 1 and n % 100 != 11) else 1 if n != 0 else 2
return forms[form]
def int2word(n):
if n > 9999: # doesn't yet work for numbers this big
raise NotImplementedError()
if n == 0:
return ZERO[0]
words = []
chunks = list(splitbyx(str(n), 3))
i = len(chunks)
for x in chunks:
i -= 1
if x == 0:
continue
n1, n2, n3 = get_digits(x)
if n3 > 0:
if n3 <= 2:
words.append(HUNDRED[n3][0])
else:
words.append(ONES[n3][0])
words.append(HUNDRED[3][0])
if n2 > 1:
words.append(TWENTIES[n2][0])
if n2 == 1:
words.append(TENS[n1][0])
elif n1 > 0 and not (i > 0 and x == 1):
words.append(ONES[n1][0])
if i > 0:
if i <= 2:
words.append(THOUSANDS[i][0])
else:
words.append(ONES[i][0])
words.append(THOUSANDS[1][0])
if len(words) > 1:
words[-1] = AND + words[-1]
return ' '.join(words)
def n2w(n):
return int2word(int(n))
def to_currency(n, currency='EUR', cents=True, seperator=','):
raise NotImplementedError()
class Num2Word_HE(object):
def to_cardinal(self, number):
return n2w(number)
def to_ordinal(self, number):
raise NotImplementedError()
if __name__ == '__main__':
yo = Num2Word_HE()
nums = [1, 11, 21, 24, 99, 100, 101, 200, 211, 345, 1000, 1011]
for num in nums:
print(num, yo.to_cardinal(num))

204
num2words/lang_ID.py Normal file
View File

@ -0,0 +1,204 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import print_function, unicode_literals
class Num2Word_ID():
BASE = {0: [],
1: ["satu"],
2: ["dua"],
3: ["tiga"],
4: ["empat"],
5: ["lima"],
6: ["enam"],
7: ["tujuh"],
8: ["delapan"],
9: ["sembilan"]}
TENS_TO = {3: "ribu",
6: "juta",
9: "miliar",
12: "triliun",
15: "kuadriliun",
18: "kuantiliun",
21: "sekstiliun",
24: "septiliun",
27: "oktiliun",
30: "noniliun",
33: "desiliun"}
errmsg_floatord = "Cannot treat float number as ordinal"
errmsg_negord = "Cannot treat negative number as ordinal"
errmsg_toobig = "Too large"
max_num = 10 ** 36
def split_by_koma(self, number):
return str(number).split('.')
def split_by_3(self, number):
"""
starting here, it groups the number by three from the tail
'1234567' -> (('1',),('234',),('567',))
:param number:str
:rtype:tuple
"""
blocks = ()
length = len(number)
if length < 3:
blocks += ((number,),)
else:
len_of_first_block = length % 3
if len_of_first_block > 0:
first_block = number[0:len_of_first_block],
blocks += first_block,
for i in range(len_of_first_block, length, 3):
next_block = (number[i:i + 3],),
blocks += next_block
return blocks
def spell(self, blocks):
"""
it adds the list of spelling to the blocks
(
('1',),('034',)) -> (('1',['satu']),('234',['tiga', 'puluh', 'empat'])
)
:param blocks: tuple
:rtype: tuple
"""
word_blocks = ()
first_block = blocks[0]
if len(first_block[0]) == 1:
if first_block[0] == '0':
spelling = ['nol']
else:
spelling = self.BASE[int(first_block[0])]
elif len(first_block[0]) == 2:
spelling = self.puluh(first_block[0])
else:
spelling = (
self.ratus(first_block[0][0]) + self.puluh(first_block[0][1:3])
)
word_blocks += (first_block[0], spelling),
for block in blocks[1:]:
spelling = self.ratus(block[0][0]) + self.puluh(block[0][1:3])
block += spelling,
word_blocks += block,
return word_blocks
def ratus(self, number):
# it is used to spell
if number == '1':
return ['seratus']
elif number == '0':
return []
else:
return self.BASE[int(number)] + ['ratus']
def puluh(self, number):
# it is used to spell
if number[0] == '1':
if number[1] == '0':
return ['sepuluh']
elif number[1] == '1':
return ['sebelas']
else:
return self.BASE[int(number[1])] + ['belas']
elif number[0] == '0':
return self.BASE[int(number[1])]
else:
return (
self.BASE[int(number[0])] + ['puluh']
+ self.BASE[int(number[1])]
)
def spell_float(self, float_part):
# spell the float number
word_list = []
for n in float_part:
if n == '0':
word_list += ['nol']
continue
word_list += self.BASE[int(n)]
return ' '.join(['', 'koma'] + word_list)
def join(self, word_blocks, float_part):
"""
join the words by first join lists in the tuple
:param word_blocks: tuple
:rtype: str
"""
word_list = []
length = len(word_blocks) - 1
first_block = word_blocks[0],
start = 0
if length == 1 and first_block[0][0] == '1':
word_list += ['seribu']
start = 1
for i in range(start, length + 1, 1):
word_list += word_blocks[i][1]
if not word_blocks[i][1]:
continue
if i == length:
break
word_list += [self.TENS_TO[(length - i) * 3]]
return ' '.join(word_list) + float_part
def to_cardinal(self, number):
if number >= self.max_num:
raise OverflowError(self.errmsg_toobig % (number, self.max_num))
minus = ''
if number < 0:
minus = 'min '
float_word = ''
n = self.split_by_koma(abs(number))
if len(n) == 2:
float_word = self.spell_float(n[1])
return minus + self.join(self.spell(self.split_by_3(n[0])), float_word)
def to_ordinal(self, number):
self.verify_ordinal(number)
out_word = self.to_cardinal(number)
if out_word == "satu":
return "pertama"
return "ke" + out_word
def to_ordinal_num(self, number):
self.verify_ordinal(number)
return "ke-" + str(number)
def to_currency(self, value):
return self.to_cardinal(value) + " rupiah"
def to_year(self, value):
return self.to_cardinal(value)
def verify_ordinal(self, value):
if not value == int(value):
raise TypeError(self.errmsg_floatord % value)
if not abs(value) == value:
raise TypeError(self.errmsg_negord % value)

208
num2words/lang_IT.py Normal file
View File

@ -0,0 +1,208 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
# Globals
# -------
ZERO = "zero"
CARDINAL_WORDS = [
ZERO, "uno", "due", "tre", "quattro", "cinque", "sei", "sette", "otto",
"nove", "dieci", "undici", "dodici", "tredici", "quattordici", "quindici",
"sedici", "diciassette", "diciotto", "diciannove"
]
ORDINAL_WORDS = [
ZERO, "primo", "secondo", "terzo", "quarto", "quinto", "sesto", "settimo",
"ottavo", "nono", "decimo", "undicesimo", "dodicesimo", "tredicesimo",
"quattordicesimo", "quindicesimo", "sedicesimo", "diciassettesimo",
"diciottesimo", "diciannovesimo"
]
# The script can extrapolate the missing numbers from the base forms.
STR_TENS = {2: "venti", 3: "trenta", 4: "quaranta", 6: "sessanta"}
# These prefixes are used for extremely big numbers.
EXPONENT_PREFIXES = [
ZERO, "m", "b", "tr", "quadr", "quint", "sest", "sett", "ott", "nov", "dec"
]
# Utils
# =====
def phonetic_contraction(string):
return (string
.replace("oo", "o") # ex. "centootto"
.replace("ao", "o") # ex. "settantaotto"
.replace("io", "o") # ex. "ventiotto"
.replace("au", "u") # ex. "trentauno"
)
def exponent_length_to_string(exponent_length):
# We always assume `exponent` to be a multiple of 3. If it's not true, then
# Num2Word_IT.big_number_to_cardinal did something wrong.
prefix = EXPONENT_PREFIXES[exponent_length // 6]
if exponent_length % 6 == 0:
return prefix + "ilione"
else:
return prefix + "iliardo"
def accentuate(string):
# This is inefficient: it may do several rewritings when deleting
# half-sentence accents. However, it is the easiest method and speed is
# not crucial (duh), so...
return " ".join(
# Deletes half-sentence accents and accentuates the last "tre"
[w.replace("tré", "tre")[:-3] + "tré"
# We shouldn't accentuate a single "tre": is has to be a composite
# word. ~~~~~~~~~~
if w[-3:] == "tre" and len(w) > 3
# Deletes half-sentence accents anyway
# ~~~~~~~~~~~~~~~~~~~~~~
else w.replace("tré", "tre")
for w in string.split()
])
def omitt_if_zero(number_to_string):
return "" if number_to_string == ZERO else number_to_string
# Main class
# ==========
class Num2Word_IT:
MINUS_PREFIX_WORD = "meno "
FLOAT_INFIX_WORD = " virgola "
def __init__(self):
pass
def float_to_words(self, float_number, ordinal=False):
if ordinal:
prefix = self.to_ordinal(int(float_number))
else:
prefix = self.to_cardinal(int(float_number))
float_part = str(float_number).split('.')[1]
postfix = " ".join(
# Drops the trailing zero and comma
[self.to_cardinal(int(c)) for c in float_part]
)
return prefix + Num2Word_IT.FLOAT_INFIX_WORD + postfix
def tens_to_cardinal(self, number):
tens = number // 10
units = number % 10
if tens in STR_TENS:
prefix = STR_TENS[tens]
else:
prefix = CARDINAL_WORDS[tens][:-1] + "anta"
postfix = omitt_if_zero(CARDINAL_WORDS[units])
return phonetic_contraction(prefix + postfix)
def hundreds_to_cardinal(self, number):
hundreds = number // 100
prefix = "cento"
if hundreds != 1:
prefix = CARDINAL_WORDS[hundreds] + prefix
postfix = omitt_if_zero(self.to_cardinal(number % 100))
return phonetic_contraction(prefix + postfix)
def thousands_to_cardinal(self, number):
thousands = number // 1000
if thousands == 1:
prefix = "mille"
else:
prefix = self.to_cardinal(thousands) + "mila"
postfix = omitt_if_zero(self.to_cardinal(number % 1000))
# "mille" and "mila" don't need any phonetic contractions
return prefix + postfix
def big_number_to_cardinal(self, number):
digits = [c for c in str(number)]
length = len(digits)
if length >= 66:
raise NotImplementedError("The given number is too large.")
# This is how many digits come before the "illion" term.
# cento miliardi => 3
# dieci milioni => 2
# un miliardo => 1
predigits = length % 3 or 3
multiplier = digits[:predigits]
exponent = digits[predigits:]
# Default infix string: "milione", "biliardo", "sestilione", ecc.
infix = exponent_length_to_string(len(exponent))
if multiplier == ["1"]:
prefix = "un "
else:
prefix = self.to_cardinal(int("".join(multiplier)))
# Plural form ~~~~~~~~~~~
infix = " " + infix[:-1] + "i"
# Read as: Does the value of exponent equal 0?
if set(exponent) != set("0"):
postfix = self.to_cardinal(int("".join(exponent)))
if " e " in postfix:
infix += ", "
else:
infix += " e "
else:
postfix = ""
return prefix + infix + postfix
def to_cardinal(self, number):
if number < 0:
string = Num2Word_IT.MINUS_PREFIX_WORD + self.to_cardinal(-number)
elif isinstance(number, float):
string = self.float_to_words(number)
elif number < 20:
string = CARDINAL_WORDS[number]
elif number < 100:
string = self.tens_to_cardinal(number)
elif number < 1000:
string = self.hundreds_to_cardinal(number)
elif number < 1000000:
string = self.thousands_to_cardinal(number)
else:
string = self.big_number_to_cardinal(number)
return accentuate(string)
def to_ordinal(self, number):
tens = number % 100
# Italian grammar is poorly defined here ¯\_(ツ)_/¯:
# centodecimo VS centodieciesimo VS centesimo decimo?
is_outside_teens = not 10 < tens < 20
if number < 0:
return Num2Word_IT.MINUS_PREFIX_WORD + self.to_ordinal(-number)
elif number % 1 != 0:
return self.float_to_words(number, ordinal=True)
elif number < 20:
return ORDINAL_WORDS[number]
elif is_outside_teens and tens % 10 == 3:
# Gets ride of the accent ~~~~~~~~~~
return self.to_cardinal(number)[:-1] + "eesimo"
elif is_outside_teens and tens % 10 == 6:
return self.to_cardinal(number) + "esimo"
else:
string = self.to_cardinal(number)[:-1]
if string[-3:] == "mil":
string += "l"
return string + "esimo"

589
num2words/lang_JA.py Normal file
View File

@ -0,0 +1,589 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import division, print_function, unicode_literals
from .base import Num2Word_Base
from .compat import strtype, to_s
from .currency import parse_currency_parts, prefix_currency
def select_text(text, reading=False, prefer=None):
"""Select the correct text from the Japanese number, reading and
alternatives"""
# select kanji number or kana reading
if reading:
text = text[1]
else:
text = text[0]
# select the preferred one or the first one from multiple alternatives
if not isinstance(text, strtype):
common = set(text) & set(prefer or set())
if len(common) == 1:
text = common.pop()
else:
text = text[0]
return text
def rendaku_merge_pairs(lpair, rpair):
"""Merge lpair < rpair while applying semi-irregular rendaku rules"""
ltext, lnum = lpair
rtext, rnum = rpair
if lnum > rnum:
raise ValueError
if rpair == ("ひゃく", 100):
if lpair == ("さん", 3):
rtext = "びゃく"
elif lpair == ("ろく", 6):
ltext = "ろっ"
rtext = "ぴゃく"
elif lpair == ("はち", 8):
ltext = "はっ"
rtext = "ぴゃく"
elif rpair == ("せん", 1000):
if lpair == ("さん", 3):
rtext = "ぜん"
elif lpair == ("はち", 8):
ltext = "はっ"
elif rpair == ("ちょう", 10**12):
if lpair == ("いち", 1):
ltext = "いっ"
elif lpair == ("はち", 8):
ltext = "はっ"
elif lpair == ("じゅう", 10):
ltext = "じゅっ"
elif rpair == ("けい", 10**16):
if lpair == ("いち", 1):
ltext = "いっ"
elif lpair == ("ろく", 6):
ltext = "ろっ"
elif lpair == ("はち", 8):
ltext = "はっ"
elif lpair == ("じゅう", 10):
ltext = "じゅっ"
elif lpair == ("ひゃく", 100):
ltext = "ひゃっ"
return ("%s%s" % (ltext, rtext), lnum * rnum)
# Source: https://www.sljfaq.org/afaq/era-list.html
# if there are multiple eras for the same year, use the last one
ERA_START = [
(645, ("大化", "たいか")),
(650, ("白雉", "はくち")),
(686, ("朱鳥", "しゅちょう")),
(701, ("大宝", "たいほう")),
(704, ("慶雲", "けいうん")),
(708, ("和銅", "わどう")),
(715, ("霊亀", "れいき")),
(717, ("養老", "ようろう")),
(724, ("神亀", "じんき")),
(729, ("天平", "てんぴょう")),
(749, ("天平感宝", "てんぴょうかんぽう")),
(749, ("天平勝宝", "てんぴょうしょうほう")),
(757, ("天平宝字", "てんぴょうじょうじ")),
(765, ("天平神護", "てんぴょうじんご")),
(767, ("神護景雲", "じんごけいうん")),
(770, ("宝亀", "ほうき")),
(781, ("天応", "てんおう")),
(782, ("延暦", "えんりゃく")),
(806, ("大同", "だいどう")),
(810, ("弘仁", "こうにん")),
(823, ("天長", "てんちょう")),
(834, ("承和", "じょうわ")),
(848, ("嘉祥", "かしょう")),
(851, ("仁寿", "にんじゅ")),
(855, ("斉衡", "さいこう")),
(857, ("天安", "てんあん")),
(859, ("貞観", "じょうがん")),
(877, ("元慶", "がんぎょう")),
(885, ("仁和", "にんな")),
(889, ("寛平", "かんぴょう")),
(898, ("昌泰", "しょうたい")),
(901, ("延喜", "えんぎ")),
(923, ("延長", "えんちょう")),
(931, ("承平", "じょうへい")),
(938, ("天慶", "てんぎょう")),
(947, ("天暦", "てんりゃく")),
(957, ("天徳", "てんとく")),
(961, ("応和", "おうわ")),
(964, ("康保", "こうほう")),
(968, ("安和", "あんな")),
(970, ("天禄", "てんろく")),
(974, ("天延", "てんえん")),
(976, ("貞元", "じょうげん")),
(979, ("天元", "てんげん")),
(983, ("永観", "えいかん")),
(985, ("寛和", "かんな")),
(987, ("永延", "えいえん")),
(989, ("永祚", "えいそ")),
(990, ("正暦", "しょうりゃく")),
(995, ("長徳", "ちょうとく")),
(999, ("長保", "ちょうほう")),
(1004, ("寛弘", "かんこう")),
(1013, ("長和", "ちょうわ")),
(1017, ("寛仁", "かんにん")),
(1021, ("治安", "じあん")),
(1024, ("万寿", "まんじゅ")),
(1028, ("長元", "ちょうげん")),
(1037, ("長暦", "ちょうりゃく")),
(1040, ("長久", "ちょうきゅう")),
(1045, ("寛徳", "かんとく")),
(1046, ("永承", "えいしょう")),
(1053, ("天喜", "てんぎ")),
(1058, ("康平", "こうへい")),
(1065, ("治暦", "じりゃく")),
(1069, ("延久", "えんきゅう")),
(1074, ("承保", "じょうほう")),
(1078, ("承暦", "じょうりゃく")),
(1081, ("永保", "えいほう")),
(1084, ("応徳", "おうとく")),
(1087, ("寛治", "かんじ")),
(1095, ("嘉保", "かほう")),
(1097, ("永長", "えいちょう")),
(1098, ("承徳", "じょうとく")),
(1099, ("康和", "こうわ")),
(1104, ("長治", "ちょうじ")),
(1106, ("嘉承", "かじょう")),
(1108, ("天仁", "てんにん")),
(1110, ("天永", "てんねい")),
(1113, ("永久", "えいきゅう")),
(1118, ("元永", "げんえい")),
(1120, ("保安", "ほうあん")),
(1124, ("天治", "てんじ")),
(1126, ("大治", "だいじ")),
(1131, ("天承", "てんしょう")),
(1132, ("長承", "ちょうしょう")),
(1135, ("保延", "ほうえん")),
(1141, ("永治", "えいじ")),
(1142, ("康治", "こうじ")),
(1144, ("天養", "てんよう")),
(1145, ("久安", "きゅうあん")),
(1151, ("仁平", "にんぺい")),
(1154, ("久寿", "きゅうじゅ")),
(1156, ("保元", "ほうげん")),
(1159, ("平治", "へいじ")),
(1160, ("永暦", "えいりゃく")),
(1161, ("応保", "おうほう")),
(1163, ("長寛", "ちょうかん")),
(1165, ("永万", "えいまん")),
(1166, ("仁安", "にんあん")),
(1169, ("嘉応", "かおう")),
(1171, ("承安", "しょうあん")),
(1175, ("安元", "あんげん")),
(1177, ("治承", "じしょう")),
(1181, ("養和", "ようわ")),
(1182, ("寿永", "じゅえい")),
(1184, ("元暦", "げんりゃく")),
(1185, ("文治", "ぶんじ")),
(1190, ("建久", "けんきゅう")),
(1199, ("正治", "しょうじ")),
(1201, ("建仁", "けんにん")),
(1204, ("元久", "げんきゅう")),
(1206, ("建永", "けんえい")),
(1207, ("承元", "じょうげん")),
(1211, ("建暦", "けんりゃく")),
(1214, ("建保", "けんぽう")),
(1219, ("承久", "じょうきゅう")),
(1222, ("貞応", "じょうおう")),
(1225, ("元仁", "げんにん")),
(1225, ("嘉禄", "かろく")),
(1228, ("安貞", "あんてい")),
(1229, ("寛喜", "かんき")),
(1232, ("貞永", "じょうえい")),
(1233, ("天福", "てんぷく")),
(1235, ("文暦", "ぶんりゃく")),
(1235, ("嘉禎", "かてい")),
(1239, ("暦仁", "りゃくにん")),
(1239, ("延応", "えんおう")),
(1240, ("仁治", "にんじ")),
(1243, ("寛元", "かんげん")),
(1247, ("宝治", "ほうじ")),
(1249, ("建長", "けんちょう")),
(1256, ("康元", "こうげん")),
(1257, ("正嘉", "しょうか")),
(1259, ("正元", "しょうげん")),
(1260, ("文応", "ぶんおう")),
(1261, ("弘長", "こうちょう")),
(1264, ("文永", "ぶんえい")),
(1275, ("健治", "けんじ")),
(1278, ("弘安", "こうあん")),
(1288, ("正応", "しょうおう")),
(1293, ("永仁", "えいにん")),
(1299, ("正安", "しょうあん")),
(1303, ("乾元", "けんげん")),
(1303, ("嘉元", "かげん")),
(1307, ("徳治", "とくじ")),
(1308, ("延慶", "えんきょう")),
(1311, ("応長", "おうちょう")),
(1312, ("正和", "しょうわ")),
(1317, ("文保", "ぶんぽう")),
(1319, ("元応", "げんおう")),
(1321, ("元亨", "げんこう")),
(1325, ("正中", "しょうちゅ")),
(1326, ("嘉暦", "かりゃく")),
(1329, ("元徳", "げんとく")),
(1331, ("元弘", "げんこう")),
(1332, ("正慶", "しょうけい")),
(1334, ("建武", "けんむ")),
(1336, ("延元", "えいげん")),
(1338, ("暦応", "りゃくおう")),
(1340, ("興国", "こうこく")),
(1342, ("康永", "こうえい")),
(1345, ("貞和", "じょうわ")),
(1347, ("正平", "しょうへい")),
(1350, ("観応", "かんおう")),
(1352, ("文和", "ぶんな")),
(1356, ("延文", "えんぶん")),
(1361, ("康安", "こうあん")),
(1362, ("貞治", "じょうじ")),
(1368, ("応安", "おうあん")),
(1370, ("建徳", "けんとく")),
(1372, ("文中", "ぶんちゅう")),
(1375, ("永和", "えいわ")),
(1375, ("天授", "てんじゅ")),
(1379, ("康暦", "こうりゃく")),
(1381, ("永徳", "えいとく")),
(1381, ("弘和", "こうわ")),
(1384, ("至徳", "しとく")),
(1384, ("元中", "げんちゅう")),
(1387, ("嘉慶", "かけい")),
(1389, ("康応", "こうおう")),
(1390, ("明徳", "めいとく")),
(1394, ("応永", "おうえい")),
(1428, ("正長", "しょうちょう")),
(1429, ("永享", "えいきょう")),
(1441, ("嘉吉", "かきつ")),
(1444, ("文安", "ぶんあん")),
(1449, ("宝徳", "ほうとく")),
(1452, ("享徳", "きょうとく")),
(1455, ("康正", "こうしょう")),
(1457, ("長禄", "ちょうろく")),
(1461, ("寛正", "かんしょう")),
(1466, ("文正", "ぶんしょう")),
(1467, ("応仁", "おうにん")),
(1469, ("文明", "ぶんめい")),
(1487, ("長享", "ちょうきょう")),
(1489, ("延徳", "えんとく")),
(1492, ("明応", "めいおう")),
(1501, ("文亀", "ぶんき")),
(1504, ("永正", "えいしょう")),
(1521, ("大永", "だいえい")),
(1528, ("享禄", "きょうろく")),
(1532, ("天文", "てんぶん")),
(1555, ("弘治", "こうじ")),
(1558, ("永禄", "えいろく")),
(1570, ("元亀", "げんき")),
(1573, ("天正", "てんしょう")),
(1593, ("文禄", "ぶんろく")),
(1596, ("慶長", "けいちょう")),
(1615, ("元和", "げんな")),
(1624, ("寛永", "かんえい")),
(1645, ("正保", "しょうほう")),
(1648, ("慶安", "けいあん")),
(1652, ("承応", "じょうおう")),
(1655, ("明暦", "めいれき")),
(1658, ("万治", "まんじ")),
(1661, ("寛文", "かんぶん")),
(1673, ("延宝", "えんぽう")),
(1681, ("天和", "てんな")),
(1684, ("貞享", "じょうきょう")),
(1688, ("元禄", "げんろく")),
(1704, ("宝永", "ほうえい")),
(1711, ("正徳", "しょうとく")),
(1716, ("享保", "きょうほう")),
(1736, ("元文", "げんぶん")),
(1741, ("寛保", "かんぽう")),
(1744, ("延享", "えんきょう")),
(1748, ("寛延", "かんえん")),
(1751, ("宝暦", "ほうれき")),
(1764, ("明和", "めいわ")),
(1773, ("安永", "あんえい")),
(1781, ("天明", "てんめい")),
(1801, ("寛政", "かんせい")),
(1802, ("享和", "きょうわ")),
(1804, ("文化", "ぶんか")),
(1818, ("文政", "ぶんせい")),
(1831, ("天保", "てんぽう")),
(1845, ("弘化", "こうか")),
(1848, ("嘉永", "かえい")),
(1855, ("安政", "あんせい")),
(1860, ("万延", "まんえい")),
(1861, ("文久", "ぶんきゅう")),
(1864, ("元治", "げんじ")),
(1865, ("慶応", "けいおう")),
(1868, ("明治", "めいじ")),
(1912, ("大正", "たいしょう")),
(1926, ("昭和", "しょうわ")),
(1989, ("平成", "へいせい")),
]
class Num2Word_JA(Num2Word_Base):
CURRENCY_FORMS = {
'JPY': (('', 'えん'), ()),
}
def set_high_numwords(self, high):
max = 4 * len(high)
for word, n in zip(high, range(max, 0, -4)):
self.cards[10 ** n] = word
def setup(self):
self.negword = "マイナス"
self.pointword = ("", "てん")
self.exclude_title = ["", "マイナス"]
self.high_numwords = [
("", "まん"), # 10**4 man
("", "おく"), # 10**8 oku
("", "ちょう"), # 10**12 chō
("", "けい"), # 10**16 kei
("", "がい"), # 10**20 gai
("", ""), # 10**24 shi
("", "じょう"), # 10**28 jō
("", "こう"), # 10**32 kō
("", "かん"), # 10**36 kan
("", "せい"), # 10**40 sei
("", "さい"), # 10**44 sai
("", "ごく"), # 10**48 goku
]
self.high_numwords.reverse()
self.mid_numwords = [
(1000, ("", "せん")),
(100, ("", "ひゃく")),
]
self.low_numwords = [
("", "じゅう"), # 10 jū
("", "きゅう"), # 9 kyū
("", "はち"), # 8 hachi
("", ("なな", "しち")), # 7 nana, shichi
("", "ろく"), # 6 roku
("", ""), # 5 go
("", ("よん", "")), # 4 yon, shi
("", "さん"), # 3 san
("", ""), # 2 ni
("", "いち"), # 1 ichi
# both are alternatives, 零 doesn't map to ゼロ or to れい
(("", ""), ("ゼロ", "れい")), # 0 ZERO, rei
]
def merge(self, lpair, rpair):
ltext, lnum = lpair
rtext, rnum = rpair
fmt = "%s%s"
# ignore lpair if lnum is 1 and rnum is less than 10000
if lnum == 1 and rnum < 10000:
return rpair
# rnum is added to lnum
elif lnum > rnum:
return (fmt % (ltext, rtext), lnum + rnum)
# rnum is multiplied by lnum
elif lnum < rnum:
return rendaku_merge_pairs(lpair, rpair)
def _ordinal_suffix(self, reading, counter):
if reading:
if counter == "":
return "ばんめ"
else:
raise NotImplementedError(
"Reading not implemented for %s" % counter)
else:
return counter + ""
def to_ordinal(self, value, reading=False, prefer=None, counter=""):
self.verify_ordinal(value)
base = self.to_cardinal(value, reading=reading, prefer=prefer)
return "%s%s" % (base, self._ordinal_suffix(reading, counter))
def to_ordinal_num(self, value, reading=False, counter=""):
return "%s%s" % (value, self._ordinal_suffix(reading, counter))
def to_year(self, val, suffix=None, longval=True, reading=False,
prefer=None, era=True):
year = val
# Gregorian calendar
if not era:
prefix = ""
if year < 0:
year = abs(year)
prefix = "きげんぜん" if reading else "紀元前"
year_words = self.to_cardinal(year, reading=reading, prefer=prefer)
if reading and year % 10 == 9:
year_words = year_words[:-3] + ""
return "%s%s%s" % (prefix, year_words, "ねん" if reading else "")
# Era calendar (default)
min_year = ERA_START[0][0]
last_era_idx = len(ERA_START) - 1
if year < min_year:
raise ValueError(
"Can't convert years less than %s to era" % min_year)
first = 0
last = last_era_idx
era_idx = None
while era_idx is None:
mid = (first + last) // 2
if mid == last_era_idx or (ERA_START[mid][0] <= year and
ERA_START[mid + 1][0] > year):
era_idx = mid
# if an era lasting less than a year is preferred, choose it
if prefer:
i = mid - 1
while i >= 0 and ERA_START[i][0] == year:
# match kanji or hiragana
if set(ERA_START[i][1]) & set(prefer):
era_idx = i
break
i -= 1
# ends up at the last index where year >= ERA_START[mid][0]
if year < ERA_START[mid][0]:
last = mid - 1
else:
first = mid + 1
era = ERA_START[era_idx]
era_name = era[1][0]
era_year = year - era[0] + 1
fmt = "%s%s"
if reading == "arabic":
era_year_words = str(era_year)
elif reading:
era_name = era[1][1]
era_year_words = (self.to_cardinal(era_year, reading=True,
prefer=prefer)
if era_year != 1 else "がん")
if era_year % 10 == 9:
era_year_words = era_year_words[:-3] + ""
fmt = "%s%sねん"
else:
era_year_words = (self.to_cardinal(era_year, reading=False,
prefer=prefer)
if era_year != 1 else "")
return fmt % (era_name, era_year_words)
def to_currency(self, val, currency="JPY", cents=False, seperator="",
adjective=False, reading=False, prefer=None):
left, right, is_negative = parse_currency_parts(
val, is_int_with_cents=cents)
try:
cr1, cr2 = self.CURRENCY_FORMS[currency]
if (cents or abs(val) != left) and not cr2:
raise ValueError('Decimals not supported for "%s"' % currency)
except KeyError:
raise NotImplementedError(
'Currency code "%s" not implemented for "%s"' %
(currency, self.__class__.__name__))
if adjective and currency in self.CURRENCY_ADJECTIVES:
cr1 = prefix_currency(self.CURRENCY_ADJECTIVES[currency], cr1)
minus_str = self.negword if is_negative else ""
return '%s%s%s%s%s' % (
minus_str,
self.to_cardinal(left, reading=reading, prefer=prefer),
cr1[1] if reading else cr1[0],
self.to_cardinal(right, reading=reading, prefer=prefer)
if cr2 else '',
(cr2[1] if reading else cr2[0]) if cr2 else '',
)
def splitnum(self, value, reading, prefer):
for elem in self.cards:
if elem > value:
continue
out = []
if value == 0:
div, mod = 1, 0
else:
div, mod = divmod(value, elem)
if div == 1:
out.append((select_text(self.cards[1], reading, prefer), 1))
else:
if div == value: # The system tallies, eg Roman Numerals
return [(
div * select_text(self.cards[elem], reading, prefer),
div * elem)]
out.append(self.splitnum(div, reading, prefer))
out.append((select_text(self.cards[elem], reading, prefer), elem))
if mod:
out.append(self.splitnum(mod, reading, prefer))
return out
def to_cardinal(self, value, reading=False, prefer=None):
try:
assert int(value) == value
except (ValueError, TypeError, AssertionError):
return self.to_cardinal_float(value, reading=reading,
prefer=prefer)
out = ""
if value < 0:
value = abs(value)
out = self.negword
if value >= self.MAXVAL:
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
val = self.splitnum(value, reading, prefer)
words, _ = self.clean(val)
return self.title(out + words)
def to_cardinal_float(self, value, reading=False, prefer=None):
prefer = prefer or ["れい"]
try:
float(value) == value
except (ValueError, TypeError, AssertionError):
raise TypeError(self.errmsg_nonnum % value)
pre, post = self.float2tuple(float(value))
post = str(post)
post = '0' * (self.precision - len(post)) + post
out = [self.to_cardinal(pre, reading=reading, prefer=prefer)]
if self.precision:
out.append(self.title(self.pointword[1 if reading else 0]))
for i in range(self.precision):
curr = int(post[i])
out.append(to_s(
self.to_cardinal(curr, reading=reading, prefer=prefer)))
return "".join(out)

148
num2words/lang_KO.py Normal file
View File

@ -0,0 +1,148 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import division, print_function, unicode_literals
from .base import Num2Word_Base
from .currency import parse_currency_parts
class Num2Word_KO(Num2Word_Base):
CURRENCY_FORMS = {
'KRW': ('', None),
'USD': ('달러', '센트'),
'JPY': ('', None)
}
def set_high_numwords(self, high):
max = 4 * len(high)
for word, n in zip(high, range(max, 0, -4)):
self.cards[10 ** n] = word
def setup(self):
super(Num2Word_KO, self).setup()
self.negword = "마이너스 "
self.pointword = ""
self.high_numwords = [
'무량대수',
'불가사의',
'나유타',
'아승기',
'항하사',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'']
self.mid_numwords = [(1000, ""), (100, "")]
self.low_numwords = ["", "", "", "", "", "", "", "", "",
"", ""]
self.ords = {"": "",
"": "",
"": "",
"": "",
"": "다섯",
"": "여섯",
"": "일곱",
"": "여덟",
"": "아홉",
"": "",
"이십": "스물",
"삼십": "서른",
"사십": "마흔",
"오십": "",
"육십": "예순",
"칠십": "일흔",
"팔십": "여든",
"구십": "아흔"}
def merge(self, lpair, rpair):
ltext, lnum = lpair
rtext, rnum = rpair
if lnum == 1 and rnum <= 10000:
return rpair
elif 10000 > lnum > rnum:
return ("%s%s" % (ltext, rtext), lnum + rnum)
elif lnum >= 10000 and lnum > rnum:
return ("%s %s" % (ltext, rtext), lnum + rnum)
else:
return ("%s%s" % (ltext, rtext), lnum * rnum)
def to_ordinal(self, value):
self.verify_ordinal(value)
if(value == 1):
return "첫 번째"
outwords = self.to_cardinal(value).split(" ")
lastwords = outwords[-1].split("")
if "" in lastwords[-1]:
ten_one = lastwords[-1].split("")
ten_one[0] = self.ords[ten_one[0] + ""]
try:
ten_one[1] = self.ords[ten_one[1]]
ten_one[0] = ten_one[0].replace("스무", "스물")
except KeyError:
pass
lastwords[-1] = ''.join(ten_one)
else:
lastwords[-1] = self.ords[lastwords[-1]]
outwords[-1] = "".join(lastwords)
return " ".join(outwords) + " 번째"
def to_ordinal_num(self, value):
self.verify_ordinal(value)
return "%s 번째" % (value)
def to_year(self, val, suffix=None, longval=True):
if val < 0:
val = abs(val)
suffix = '기원전' if not suffix else suffix
valtext = self.to_cardinal(val)
return ("%s" % valtext if not suffix
else "%s %s" % (suffix, valtext))
def to_currency(self, val, currency="KRW", cents=False, seperator="",
adjective=False):
left, right, is_negative = parse_currency_parts(
val, is_int_with_cents=cents)
try:
cr1, cr2 = self.CURRENCY_FORMS[currency]
if (cents or right) and not cr2:
raise ValueError('Decimals not supported for "%s"' % currency)
except KeyError:
raise NotImplementedError(
'Currency code "%s" not implemented for "%s"' %
(currency, self.__class__.__name__))
minus_str = self.negword if is_negative else ""
return '%s%s%s%s%s' % (
minus_str,
''.join(self.to_cardinal(left).split()),
cr1,
' ' + self.to_cardinal(right)
if cr2 else '',
cr2 if cr2 else '',
)

179
num2words/lang_LT.py Normal file
View File

@ -0,0 +1,179 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from .base import Num2Word_Base
from .utils import get_digits, splitbyx
ZERO = ('nulis',)
ONES_FEMININE = {
1: ('viena',),
2: ('dvi',),
3: ('trys',),
4: ('keturios',),
5: ('penkios',),
6: ('šešios',),
7: ('septynios',),
8: ('aštuonios',),
9: ('devynios',),
}
ONES = {
1: ('vienas',),
2: ('du',),
3: ('trys',),
4: ('keturi',),
5: ('penki',),
6: ('šeši',),
7: ('septyni',),
8: ('aštuoni',),
9: ('devyni',),
}
TENS = {
0: ('dešimt',),
1: ('vienuolika',),
2: ('dvylika',),
3: ('trylika',),
4: ('keturiolika',),
5: ('penkiolika',),
6: ('šešiolika',),
7: ('septyniolika',),
8: ('aštuoniolika',),
9: ('devyniolika',),
}
TWENTIES = {
2: ('dvidešimt',),
3: ('trisdešimt',),
4: ('keturiasdešimt',),
5: ('penkiasdešimt',),
6: ('šešiasdešimt',),
7: ('septyniasdešimt',),
8: ('aštuoniasdešimt',),
9: ('devyniasdešimt',),
}
HUNDRED = ('šimtas', 'šimtai')
THOUSANDS = {
1: ('tūkstantis', 'tūkstančiai', 'tūkstančių'),
2: ('milijonas', 'milijonai', 'milijonų'),
3: ('milijardas', 'milijardai', 'milijardų'),
4: ('trilijonas', 'trilijonai', 'trilijonų'),
5: ('kvadrilijonas', 'kvadrilijonai', 'kvadrilijonų'),
6: ('kvintilijonas', 'kvintilijonai', 'kvintilijonų'),
7: ('sikstilijonas', 'sikstilijonai', 'sikstilijonų'),
8: ('septilijonas', 'septilijonai', 'septilijonų'),
9: ('oktilijonas', 'oktilijonai', 'oktilijonų'),
10: ('naintilijonas', 'naintilijonai', 'naintilijonų'),
}
GENERIC_CENTS = ('centas', 'centai', 'centų')
class Num2Word_LT(Num2Word_Base):
CURRENCY_FORMS = {
'LTL': (('litas', 'litai', 'litų'), GENERIC_CENTS),
'EUR': (('euras', 'eurai', 'eurų'), GENERIC_CENTS),
'USD': (('doleris', 'doleriai', 'dolerių'), GENERIC_CENTS),
'GBP': (
('svaras sterlingų', 'svarai sterlingų', 'svarų sterlingų'),
('pensas', 'pensai', 'pensų')
),
'PLN': (
('zlotas', 'zlotai', 'zlotų'),
('grašis', 'grašiai', 'grašių')),
'RUB': (
('rublis', 'rubliai', 'rublių'),
('kapeika', 'kapeikos', 'kapeikų')
),
}
def setup(self):
self.negword = "minus"
self.pointword = "kablelis"
def pluralize(self, n, forms):
n1, n2, n3 = get_digits(n)
if n2 == 1 or n1 == 0 or n == 0:
return forms[2]
elif n1 == 1:
return forms[0]
else:
return forms[1]
def to_cardinal(self, number):
n = str(number).replace(',', '.')
base_str, n = self.parse_minus(n)
if '.' in n:
left, right = n.split('.')
return '%s%s %s %s' % (
base_str,
self._int2word(int(left)),
self.pointword,
self._int2word(int(right))
)
else:
return "%s%s" % (base_str, self._int2word(int(n)))
def to_ordinal(self, number):
raise NotImplementedError()
def _cents_verbose(self, number, currency):
return self._int2word(number, currency == 'RUB')
def _int2word(self, n, feminine=False):
if n == 0:
return ZERO[0]
words = []
chunks = list(splitbyx(str(n), 3))
i = len(chunks)
for x in chunks:
i -= 1
if x == 0:
continue
n1, n2, n3 = get_digits(x)
if n3 > 0:
words.append(ONES[n3][0])
if n3 > 1:
words.append(HUNDRED[1])
else:
words.append(HUNDRED[0])
if n2 > 1:
words.append(TWENTIES[n2][0])
if n2 == 1:
words.append(TENS[n1][0])
elif n1 > 0:
if (i == 1 or feminine and i == 0) and n < 1000:
words.append(ONES_FEMININE[n1][0])
else:
words.append(ONES[n1][0])
if i > 0:
words.append(self.pluralize(x, THOUSANDS[i]))
return ' '.join(words)

186
num2words/lang_LV.py Normal file
View File

@ -0,0 +1,186 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from .base import Num2Word_Base
from .utils import get_digits, splitbyx
ZERO = ('nulle',)
ONES = {
1: ('viens',),
2: ('divi',),
3: ('trīs',),
4: ('četri',),
5: ('pieci',),
6: ('seši',),
7: ('septiņi',),
8: ('astoņi',),
9: ('deviņi',),
}
TENS = {
0: ('desmit',),
1: ('vienpadsmit',),
2: ('divpadsmit',),
3: ('trīspadsmit',),
4: ('četrpadsmit',),
5: ('piecpadsmit',),
6: ('sešpadsmit',),
7: ('septiņpadsmit',),
8: ('astoņpadsmit',),
9: ('deviņpadsmit',),
}
TWENTIES = {
2: ('divdesmit',),
3: ('trīsdesmit',),
4: ('četrdesmit',),
5: ('piecdesmit',),
6: ('sešdesmit',),
7: ('septiņdesmit',),
8: ('astoņdesmit',),
9: ('deviņdesmit',),
}
HUNDRED = ('simts', 'simti', 'simtu')
THOUSANDS = {
1: ('tūkstotis', 'tūkstoši', 'tūkstošu'),
2: ('miljons', 'miljoni', 'miljonu'),
3: ('miljards', 'miljardi', 'miljardu'),
4: ('triljons', 'triljoni', 'triljonu'),
5: ('kvadriljons', 'kvadriljoni', 'kvadriljonu'),
6: ('kvintiljons', 'kvintiljoni', 'kvintiljonu'),
7: ('sikstiljons', 'sikstiljoni', 'sikstiljonu'),
8: ('septiljons', 'septiljoni', 'septiljonu'),
9: ('oktiljons', 'oktiljoni', 'oktiljonu'),
10: ('nontiljons', 'nontiljoni', 'nontiljonu'),
}
GENERIC_DOLLARS = ('dolārs', 'dolāri', 'dolāru')
GENERIC_CENTS = ('cents', 'centi', 'centu')
GENERIC_KRONA = ('krona', 'kronas', 'kronu')
GENERIC_ERA = ('ēre', 'ēras', 'ēru')
class Num2Word_LV(Num2Word_Base):
"""
Sadly we have a legal form (used in legal and finance documents):
http://www.eiro.lv/files/upload/files/Eiro_rakstiba-1.pdf
https://likumi.lv/doc.php?id=254741
http://eur-lex.europa.eu/legal-content/LV/TXT/HTML/?uri=CELEX:31998R0974&from=LV
Source: http://publications.europa.eu/code/lv/lv-5000500.htm
"""
CURRENCY_FORMS = {
'AUD': (GENERIC_DOLLARS, GENERIC_CENTS),
'CAD': (GENERIC_DOLLARS, GENERIC_CENTS),
# repalced by EUR
'EEK': (GENERIC_KRONA, GENERIC_CENTS),
'EUR': (('eiro', 'eiro', 'eiro'), GENERIC_CENTS),
'EUR_LEGAL': (('euro', 'euro', 'euro'), GENERIC_CENTS),
'GBP': (
('sterliņu mārciņa', 'sterliņu mārciņas', 'sterliņu mārciņu'),
('penss', 'pensi', 'pensu')),
# replaced by EUR
'LTL': (('lits', 'liti', 'litu'), GENERIC_CENTS),
# replaced by EUR
'LVL': (('lats', 'lati', 'latu'),
('santīms', 'santīmi', 'santīmu')),
'USD': (GENERIC_DOLLARS, GENERIC_CENTS),
'RUB': (('rublis', 'rubļi', 'rubļu'),
('kapeika', 'kapeikas', 'kapeiku')),
'SEK': (GENERIC_KRONA, GENERIC_ERA),
'NOK': (GENERIC_KRONA, GENERIC_ERA),
'PLN': (('zlots', 'zloti', 'zlotu'),
('grasis', 'graši', 'grašu')),
}
CURRENCY_ADJECTIVES = {
'AUD': 'Austrālijas',
'CAD': 'Kanādas',
'EEK': 'Igaunijas',
'USD': 'ASV',
'RUB': 'Kreivijas',
'SEK': 'Zviedrijas',
'NOK': 'Norvēģijas',
}
def setup(self):
self.negword = "mīnus"
self.pointword = "komats"
def to_cardinal(self, number):
n = str(number).replace(',', '.')
base_str, n = self.parse_minus(n)
if '.' in n:
left, right = n.split('.')
return '%s%s %s %s' % (
base_str,
self._int2word(int(left)),
self.pointword,
self._int2word(int(right))
)
else:
return "%s%s" % (base_str, self._int2word(int(n)))
def pluralize(self, n, forms):
form = 0 if (n % 10 == 1 and n % 100 != 11) else 1 if n != 0 else 2
return forms[form]
def to_ordinal(self, number):
raise NotImplementedError()
def _int2word(self, n):
if n == 0:
return ZERO[0]
words = []
chunks = list(splitbyx(str(n), 3))
i = len(chunks)
for x in chunks:
i -= 1
if x == 0:
continue
n1, n2, n3 = get_digits(x)
if n3 > 0:
if n3 == 1 and n2 == 0 and n1 > 0:
words.append(HUNDRED[2])
elif n3 > 1:
words.append(ONES[n3][0])
words.append(HUNDRED[1])
else:
words.append(HUNDRED[0])
if n2 > 1:
words.append(TWENTIES[n2][0])
if n2 == 1:
words.append(TENS[n1][0])
elif n1 > 0 and not (i > 0 and x == 1):
words.append(ONES[n1][0])
if i > 0:
words.append(self.pluralize(x, THOUSANDS[i]))
return ' '.join(words)

152
num2words/lang_NL.py Normal file
View File

@ -0,0 +1,152 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import print_function, unicode_literals
from .lang_EU import Num2Word_EU
class Num2Word_NL(Num2Word_EU):
CURRENCY_FORMS = {
'EUR': (('euro', 'euros'), ('cent', 'cents')),
}
GIGA_SUFFIX = "iljard"
MEGA_SUFFIX = "iljoen"
def setup(self):
super(Num2Word_NL, self).setup()
self.negword = "min "
self.pointword = "komma"
# "Cannot treat float %s as ordinal."
self.errmsg_floatord = (
"Het zwevende puntnummer %s kan niet omgezet worden " +
"naar een ordernummer."
)
# "type(((type(%s)) ) not in [long, int, float]"
self.errmsg_nonnum = (
"Alleen nummers (type (%s)) kunnen naar " +
"woorden omgezet worden."
)
# "Cannot treat negative num %s as ordinal."
self.errmsg_negord = (
"Het negatieve getal %s kan niet omgezet " +
"worden naar een ordernummer."
)
# "abs(%s) must be less than %s."
self.errmsg_toobig = "Het getal %s moet minder zijn dan %s."
self.exclude_title = []
lows = ["non", "okt", "sept", "sext", "quint", "quadr", "tr", "b", "m"]
units = ["", "un", "duo", "tre", "quattuor", "quin", "sex", "sept",
"okto", "novem"]
tens = ["dez", "vigint", "trigint", "quadragint", "quinquagint",
"sexagint", "septuagint", "oktogint", "nonagint"]
self.high_numwords = (
["zend"] + self.gen_high_numwords(units, tens, lows))
self.mid_numwords = [(1000, "duizend"), (100, "honderd"),
(90, "negentig"), (80, "tachtig"),
(70, "zeventig"), (60, "zestig"),
(50, "vijftig"), (40, "veertig"),
(30, "dertig")]
self.low_numwords = ["twintig", "negentien", "achttien", "zeventien",
"zestien", "vijftien", "veertien", "dertien",
"twaalf", "elf", "tien", "negen", "acht", "zeven",
"zes", "vijf", "vier", "drie", "twee", "één",
"nul"]
self.ords = {"één": "eerst",
"twee": "tweed",
"drie": "derd",
"vier": "vierd",
"vijf": "vijfd",
"zes": "zesd",
"zeven": "zevend",
"acht": "achtst",
"negen": "negend",
"tien": "tiend",
"elf": "elfd",
"twaalf": "twaalfd",
"ig": "igst",
"erd": "erdst",
"end": "endst",
"joen": "joenst",
"rd": "rdst"}
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if cnum == 1:
if nnum < 10 ** 6:
return next
ctext = "een"
if nnum > cnum:
if nnum >= 10 ** 6:
ctext += " "
val = cnum * nnum
else:
if nnum < 10 < cnum < 100:
if nnum == 1:
ntext = "een"
if ntext.endswith("e"):
ntext += "ën" # "n"
else:
ntext += "en"
ntext, ctext = ctext, ntext # + "en"
elif cnum >= 10 ** 6:
ctext += " "
val = cnum + nnum
word = ctext + ntext
return word, val
def to_ordinal(self, value):
self.verify_ordinal(value)
outword = self.to_cardinal(value)
for key in self.ords:
if outword.endswith(key):
outword = outword[:len(outword) - len(key)] + self.ords[key]
break
return outword + "e"
def to_ordinal_num(self, value):
self.verify_ordinal(value)
return str(value) + "."
def pluralize(self, n, forms):
"""
:param n:
:param forms:
:return:
gettext form is nplurals=2; plural=(n != 1);
but this claims https://onzetaal.nl/taaladvies/euro-euros/
not sure if it's applied only to euro
"""
return forms[0]
def to_year(self, val, longval=True):
if not (val // 100) % 10:
return self.to_cardinal(val)
return self.to_splitnum(val, hightxt="honderd", longval=longval)

108
num2words/lang_NO.py Normal file
View File

@ -0,0 +1,108 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import division, print_function, unicode_literals
from . import lang_EU
class Num2Word_NO(lang_EU.Num2Word_EU):
GIGA_SUFFIX = "illard"
MEGA_SUFFIX = "illion"
def set_high_numwords(self, high):
cap = 3 + 6 * len(high)
for word, n in zip(high, range(cap, 3, -6)):
if self.GIGA_SUFFIX:
self.cards[10 ** n] = word + self.GIGA_SUFFIX
if self.MEGA_SUFFIX:
self.cards[10 ** (n - 3)] = word + self.MEGA_SUFFIX
def setup(self):
super(Num2Word_NO, self).setup()
self.negword = "minus "
self.pointword = "komma"
self.exclude_title = ["og", "komma", "minus"]
self.mid_numwords = [(1000, "tusen"), (100, "hundre"),
(90, "nitti"), (80, "\xe5tti"), (70, "sytti"),
(60, "seksti"), (50, "femti"), (40, "f\xf8rti"),
(30, "tretti")]
self.low_numwords = ["tjue", "nitten", "atten", "sytten",
"seksten", "femten", "fjorten", "tretten",
"tolv", "elleve", "ti", "ni", "\xe5tte",
"syv", "seks", "fem", "fire", "tre", "to",
"en", "null"]
self.ords = {"en": "f\xf8rste",
"to": "andre",
"tre": "tredje",
"fire": "fjerde",
"fem": "femte",
"seks": "sjette",
"syv": "syvende",
"\xe5tte": "\xe5ttende",
"ni": "niende",
"ti": "tiende",
"elleve": "ellevte",
"tolv": "tolvte",
"tjue": "tjuende"}
def merge(self, lpair, rpair):
ltext, lnum = lpair
rtext, rnum = rpair
if lnum == 1 and rnum < 100:
return (rtext, rnum)
elif 100 > lnum > rnum:
return ("%s-%s" % (ltext, rtext), lnum + rnum)
elif lnum >= 100 > rnum:
return ("%s og %s" % (ltext, rtext), lnum + rnum)
elif rnum > lnum:
return ("%s %s" % (ltext, rtext), lnum * rnum)
return ("%s, %s" % (ltext, rtext), lnum + rnum)
def to_ordinal(self, value):
self.verify_ordinal(value)
outwords = self.to_cardinal(value).split(" ")
lastwords = outwords[-1].split("-")
lastword = lastwords[-1].lower()
try:
lastword = self.ords[lastword]
except KeyError:
if lastword[-2:] == "ti":
lastword = lastword + "ende"
else:
lastword += "de"
lastwords[-1] = self.title(lastword)
outwords[-1] = "".join(lastwords)
return " ".join(outwords)
def to_ordinal_num(self, value):
self.verify_ordinal(value)
return "%s%s" % (value, self.to_ordinal(value)[-2:])
def to_year(self, val, longval=True):
if not (val // 100) % 10:
return self.to_cardinal(val)
return self.to_splitnum(val, hightxt="hundre", jointxt="og",
longval=longval)
def to_currency(self, val, longval=True):
return self.to_splitnum(val, hightxt="krone/r", lowtxt="\xf8re/r",
jointxt="og", longval=longval, cents=True)

165
num2words/lang_PL.py Normal file
View File

@ -0,0 +1,165 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from .base import Num2Word_Base
from .utils import get_digits, splitbyx
ZERO = ('zero',)
ONES = {
1: ('jeden',),
2: ('dwa',),
3: ('trzy',),
4: ('cztery',),
5: ('pięć',),
6: ('sześć',),
7: ('siedem',),
8: ('osiem',),
9: ('dziewięć',),
}
TENS = {
0: ('dziesięć',),
1: ('jedenaście',),
2: ('dwanaście',),
3: ('trzynaście',),
4: ('czternaście',),
5: ('piętnaście',),
6: ('szesnaście',),
7: ('siedemnaście',),
8: ('osiemnaście',),
9: ('dziewiętnaście',),
}
TWENTIES = {
2: ('dwadzieścia',),
3: ('trzydzieści',),
4: ('czterdzieści',),
5: ('pięćdziesiąt',),
6: ('sześćdziesiąt',),
7: ('siedemdziesiąt',),
8: ('osiemdziesiąt',),
9: ('dziewięćdzisiąt',),
}
HUNDREDS = {
1: ('sto',),
2: ('dwieście',),
3: ('trzysta',),
4: ('czterysta',),
5: ('pięćset',),
6: ('sześćset',),
7: ('siedemset',),
8: ('osiemset',),
9: ('dziewięćset',),
}
THOUSANDS = {
1: ('tysiąc', 'tysiące', 'tysięcy'), # 10^3
2: ('milion', 'miliony', 'milionów'), # 10^6
3: ('miliard', 'miliardy', 'miliardów'), # 10^9
4: ('bilion', 'biliony', 'bilionów'), # 10^12
5: ('biliard', 'biliardy', 'biliardów'), # 10^15
6: ('trylion', 'tryliony', 'trylionów'), # 10^18
7: ('tryliard', 'tryliardy', 'tryliardów'), # 10^21
8: ('kwadrylion', 'kwadryliony', 'kwadrylionów'), # 10^24
9: ('kwadryliard', 'kwadryliardy', 'kwadryliardów'), # 10^27
10: ('kwintylion', 'kwintyliony', 'kwintylionów'), # 10^30
11: ('kwintyliard', 'kwintyliardy', 'kwintyliardów'), # 10^33
12: ('sekstylion', 'sekstyliony', 'sekstylionów'), # 10^36
13: ('sekstyliard', 'sekstyliardy', 'sekstyliardów'), # 10^39
14: ('septylion', 'septyliony', 'septylionów'), # 10^42
15: ('septyliard', 'septyliardy', 'septyliardów'), # 10^45
16: ('oktylion', 'oktyliony', 'oktylionów'), # 10^48
17: ('oktyliard', 'oktyliardy', 'oktyliardów'), # 10^51
18: ('nonylion', 'nonyliony', 'nonylionów'), # 10^54
19: ('nonyliard', 'nonyliardy', 'nonyliardów'), # 10^57
20: ('decylion', 'decyliony', 'decylionów'), # 10^60
21: ('decyliard', 'decyliardy', 'decyliardów'), # 10^63
}
class Num2Word_PL(Num2Word_Base):
CURRENCY_FORMS = {
'PLN': (
('złoty', 'złote', 'złotych'), ('grosz', 'grosze', 'groszy')
),
'EUR': (
('euro', 'euro', 'euro'), ('cent', 'centy', 'centów')
),
}
def setup(self):
self.negword = "minus"
self.pointword = "przecinek"
def to_cardinal(self, number):
n = str(number).replace(',', '.')
if '.' in n:
left, right = n.split('.')
return u'%s %s %s' % (
self._int2word(int(left)),
self.pointword,
self._int2word(int(right))
)
else:
return self._int2word(int(n))
def pluralize(self, n, forms):
if n == 1:
form = 0
elif 5 > n % 10 > 1 and (n % 100 < 10 or n % 100 > 20):
form = 1
else:
form = 2
return forms[form]
def to_ordinal(self, number):
raise NotImplementedError()
def _int2word(self, n):
if n == 0:
return ZERO[0]
words = []
chunks = list(splitbyx(str(n), 3))
i = len(chunks)
for x in chunks:
i -= 1
if x == 0:
continue
n1, n2, n3 = get_digits(x)
if n3 > 0:
words.append(HUNDREDS[n3][0])
if n2 > 1:
words.append(TWENTIES[n2][0])
if n2 == 1:
words.append(TENS[n1][0])
elif n1 > 0 and not (i > 0 and x == 1):
words.append(ONES[n1][0])
if i > 0:
words.append(self.pluralize(x, THOUSANDS[i]))
return ' '.join(words)

246
num2words/lang_PT.py Normal file
View File

@ -0,0 +1,246 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import division, unicode_literals
import re
from .lang_EU import Num2Word_EU
DOLLAR = ('dólar', 'dólares')
CENTS = ('cêntimo', 'cêntimos')
class Num2Word_PT(Num2Word_EU):
CURRENCY_FORMS = {
'AUD': (DOLLAR, CENTS),
'CAD': (DOLLAR, CENTS),
'EUR': (('euro', 'euros'), CENTS),
'GBP': (('libra', 'libras'), ('péni', 'pence')),
'USD': (DOLLAR, CENTS),
}
GIGA_SUFFIX = None
MEGA_SUFFIX = "ilião"
def setup(self):
super(Num2Word_PT, self).setup()
lows = ["quatr", "tr", "b", "m"]
self.high_numwords = self.gen_high_numwords([], [], lows)
self.negword = "menos "
self.pointword = "vírgula"
self.exclude_title = ["e", "vírgula", "menos"]
self.mid_numwords = [
(1000, "mil"), (100, "cem"), (90, "noventa"),
(80, "oitenta"), (70, "setenta"), (60, "sessenta"),
(50, "cinquenta"), (40, "quarenta"), (30, "trinta")
]
self.low_numwords = [
"vinte", "dezanove", "dezoito", "dezassete", "dezasseis",
"quinze", "catorze", "treze", "doze", "onze", "dez",
"nove", "oito", "sete", "seis", "cinco", "quatro", "três", "dois",
"um", "zero"
]
self.ords = [
{
0: "",
1: "primeiro",
2: "segundo",
3: "terceiro",
4: "quarto",
5: "quinto",
6: "sexto",
7: "sétimo",
8: "oitavo",
9: "nono",
},
{
0: "",
1: "décimo",
2: "vigésimo",
3: "trigésimo",
4: "quadragésimo",
5: "quinquagésimo",
6: "sexagésimo",
7: "septuagésimo",
8: "octogésimo",
9: "nonagésimo",
},
{
0: "",
1: "centésimo",
2: "ducentésimo",
3: "tricentésimo",
4: "quadrigentésimo",
5: "quingentésimo",
6: "seiscentésimo",
7: "septigentésimo",
8: "octigentésimo",
9: "nongentésimo",
},
]
self.thousand_separators = {
3: "milésimo",
6: "milionésimo",
9: "milésimo milionésimo",
12: "bilionésimo",
15: "milésimo bilionésimo"
}
self.hundreds = {
1: "cento",
2: "duzentos",
3: "trezentos",
4: "quatrocentos",
5: "quinhentos",
6: "seiscentos",
7: "setecentos",
8: "oitocentos",
9: "novecentos",
}
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if cnum == 1:
if nnum < 1000000:
return next
ctext = "um"
elif cnum == 100 and not nnum % 1000 == 0:
ctext = "cento"
if nnum < cnum:
if cnum < 100:
return ("%s e %s" % (ctext, ntext), cnum + nnum)
return ("%s e %s" % (ctext, ntext), cnum + nnum)
elif (not nnum % 1000000000) and cnum > 1:
ntext = ntext[:-4] + "liões"
elif (not nnum % 1000000) and cnum > 1:
ntext = ntext[:-4] + "lhões"
# correct "milião" to "milhão"
if ntext == 'milião':
ntext = 'milhão'
if nnum == 100:
ctext = self.hundreds[cnum]
ntext = ""
else:
ntext = " " + ntext
return (ctext + ntext, cnum * nnum)
def to_cardinal(self, value):
result = super(Num2Word_PT, self).to_cardinal(value)
# Transforms "mil e cento e catorze" into "mil cento e catorze"
# Transforms "cem milhões e duzentos mil e duzentos e dez" em "cem
# milhões duzentos mil duzentos e dez" but "cem milhões e duzentos
# mil e duzentos" in "cem milhões duzentos mil e duzentos" and not in
# "cem milhões duzentos mil duzentos"
for ext in (
'mil', 'milhão', 'milhões', 'mil milhões',
'bilião', 'biliões', 'mil biliões'):
if re.match('.*{} e \\w*entos? (?=.*e)'.format(ext), result):
result = result.replace(
'{} e'.format(ext), '{}'.format(ext)
)
return result
# for the ordinal conversion the code is similar to pt_BR code,
# although there are other rules that are probably more correct in
# Portugal. Concerning numbers from 2000th on, saying "dois
# milésimos" instead of "segundo milésimo" (the first number
# would be used in the cardinal form instead of the ordinal) is better.
# This was not implemented.
# source:
# https://ciberduvidas.iscte-iul.pt/consultorio/perguntas/a-forma-por-extenso-de-2000-e-de-outros-ordinais/16428
def to_ordinal(self, value):
# Before changing this function remember this is used by pt-BR
# so act accordingly
self.verify_ordinal(value)
result = []
value = str(value)
thousand_separator = ''
for idx, char in enumerate(value[::-1]):
if idx and idx % 3 == 0:
thousand_separator = self.thousand_separators[idx]
if char != '0' and thousand_separator:
# avoiding "segundo milionésimo milésimo" for 6000000,
# for instance
result.append(thousand_separator)
thousand_separator = ''
result.append(self.ords[idx % 3][int(char)])
result = ' '.join(result[::-1])
result = result.strip()
result = re.sub('\\s+', ' ', result)
if result.startswith('primeiro') and value != '1':
# avoiding "primeiro milésimo", "primeiro milionésimo" and so on
result = result[9:]
return result
def to_ordinal_num(self, value):
# Before changing this function remember this is used by pt-BR
# so act accordingly
self.verify_ordinal(value)
return "%sº" % (value)
def to_year(self, val, longval=True):
# Before changing this function remember this is used by pt-BR
# so act accordingly
if val < 0:
return self.to_cardinal(abs(val)) + ' antes de Cristo'
return self.to_cardinal(val)
def to_currency(self, val, currency='EUR', cents=True, seperator=' e',
adjective=False):
# change negword because base.to_currency() does not need space after
backup_negword = self.negword
self.negword = self.negword[:-1]
result = super(Num2Word_PT, self).to_currency(
val, currency=currency, cents=cents, seperator=seperator,
adjective=adjective)
# undo the change on negword
self.negword = backup_negword
# transforms "milhões euros" em "milhões de euros"
try:
cr1, _ = self.CURRENCY_FORMS[currency]
except KeyError:
raise NotImplementedError(
'Currency code "%s" not implemented for "%s"' %
(currency, self.__class__.__name__))
for ext in (
'milhão', 'milhões', 'bilião',
'biliões', 'trilião', 'triliões'):
if re.match('.*{} (?={})'.format(ext, cr1[1]), result):
result = result.replace(
'{}'.format(ext), '{} de'.format(ext), 1
)
# do not print "e zero cêntimos"
result = result.replace(' e zero cêntimos', '')
return result

115
num2words/lang_PT_BR.py Normal file
View File

@ -0,0 +1,115 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import division, unicode_literals
import re
from . import lang_PT
class Num2Word_PT_BR(lang_PT.Num2Word_PT):
def set_high_numwords(self, high):
max = 3 + 3*len(high)
for word, n in zip(high, range(max, 3, -3)):
self.cards[10**n] = word + "ilhão"
def setup(self):
super(Num2Word_PT_BR, self).setup()
self.low_numwords[1] = 'dezenove'
self.low_numwords[3] = 'dezessete'
self.low_numwords[4] = 'dezesseis'
self.thousand_separators = {
3: "milésimo",
6: "milionésimo",
9: "bilionésimo",
12: "trilionésimo",
15: "quadrilionésimo"
}
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if cnum == 1:
if nnum < 1000000:
return next
ctext = "um"
elif cnum == 100 and not nnum == 1000:
ctext = "cento"
if nnum < cnum:
if cnum < 100:
return ("%s e %s" % (ctext, ntext), cnum + nnum)
return ("%s e %s" % (ctext, ntext), cnum + nnum)
elif (not nnum % 1000000) and cnum > 1:
ntext = ntext[:-4] + "lhões"
if nnum == 100:
ctext = self.hundreds[cnum]
ntext = ""
else:
ntext = " " + ntext
return (ctext + ntext, cnum * nnum)
def to_cardinal(self, value):
result = lang_PT.Num2Word_EU.to_cardinal(self, value)
# Transforms "mil E cento e catorze reais" into "mil, cento e catorze
# reais"
for ext in (
'mil', 'milhão', 'milhões', 'bilhão', 'bilhões',
'trilhão', 'trilhões', 'quatrilhão', 'quatrilhões'):
if re.match('.*{} e \\w*ento'.format(ext), result):
result = result.replace(
'{} e'.format(ext), '{},'.format(ext), 1
)
return result
def to_currency(self, val, longval=True):
integer_part, decimal_part = ('%.2f' % val).split('.')
result = self.to_cardinal(int(integer_part))
appended_currency = False
for ext in (
'milhão', 'milhões', 'bilhão', 'bilhões',
'trilhão', 'trilhões', 'quatrilhão', 'quatrilhões'):
if result.endswith(ext):
result += ' de reais'
appended_currency = True
if result in ['um', 'menos um']:
result += ' real'
appended_currency = True
if not appended_currency:
result += ' reais'
if int(decimal_part):
cents = self.to_cardinal(int(decimal_part))
result += ' e ' + cents
if cents == 'um':
result += ' centavo'
else:
result += ' centavos'
return result

136
num2words/lang_RO.py Normal file
View File

@ -0,0 +1,136 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import division, print_function, unicode_literals
from . import lang_EU
class Num2Word_RO(lang_EU.Num2Word_EU):
GIGA_SUFFIX = "iliard/e"
MEGA_SUFFIX = "ilion"
# inflection for million follows different rule
MEGA_SUFFIX_I = "ilioane"
def setup(self):
super(Num2Word_RO, self).setup()
self.negword = "minus "
self.pointword = "virgulă"
self.exclude_title = ["și", "virgulă", "minus"]
self.errmsg_toobig = (
"Numărul e prea mare pentru a fi convertit în cuvinte."
)
self.mid_numwords = [(1000, "mie/i"), (100, "sută/e"),
(90, "nouăzeci"), (80, "optzeci"),
(70, "șaptezeci"), (60, "șaizeci"),
(50, "cincizeci"), (40, "patruzeci"),
(30, "treizeci")]
self.low_numwords = ["douăzeci", "nouăsprezece", "optsprezece",
"șaptesprezece", "șaisprezece", "cincisprezece",
"paisprezece", "treisprezece", "doisprezece",
"unsprezece", "zece", "nouă", "opt", "șapte",
"șase", "cinci", "patru", "trei", "doi",
"unu", "zero"]
self.gen_numwords = ["", "o", "două", "trei", "patru", "cinci",
"șase", "șapte", "opt", "nouă"]
self.gen_numwords_m = ["", "un", "două", "trei", "patru", "cinci",
"șase", "șapte", "opt", "nouă"]
self.numwords_inflections = {
100: self.gen_numwords,
1000: self.gen_numwords,
1000000: self.gen_numwords_m,
1000000000: self.gen_numwords_m
}
self.ords = {"unu": "primul",
"doi": "al doilea",
"three": "al treilea",
"cinci": "al cincilea",
"opt": "al optulea",
"nouă": "al nouălea",
"doisprezece": "al doisprezecelea"}
def merge(self, lpair, rpair):
ltext, lnum = lpair
rtext, rnum = rpair
rtext_i = self.inflect(rnum, rtext)
if lnum > 1 and rtext_i.endswith(self.MEGA_SUFFIX):
rtext_i = rtext_i.replace(self.MEGA_SUFFIX, self.MEGA_SUFFIX_I)
if 1 <= lnum < 10:
if rnum not in self.numwords_inflections:
return (rtext, rnum)
else:
rtext_i = self.inflect(lnum * rnum, rtext)
lresult = (self.numwords_inflections[rnum][lnum], rtext_i)
return ("%s %s" % lresult, rnum)
elif 10 < lnum < 100:
if lnum % 10 == 0:
return ("%s și %s" % (ltext, rtext), lnum + rnum)
else:
return ("%s %s" % (ltext, rtext_i), lnum * rnum)
else:
if rnum in self.numwords_inflections:
rtext_i = self.inflect(lnum * rnum, rtext)
return ("%s %s" % (ltext, rtext_i), lnum * rnum)
def to_ordinal(self, value):
self.verify_ordinal(value)
if value == 1:
return "primul"
else:
value = self.to_cardinal(value)
return "al %slea" % (value)
def to_ordinal_num(self, value):
self.verify_ordinal(value)
if value == 1:
return "1-ul"
return "al %s-lea" % (value)
def inflect(self, value, text):
text = text.split("/")
if value in (1, 100, 1000, 100000, 1000000000):
return text[0]
if len(text) > 1 and text[0][-1] in "aăeiou":
text[0] = text[0][:-1]
return "".join(text)
def to_currency(self, val, longval=True, old=False):
cents = int(round(val*100))
result = self.to_splitnum(cents, hightxt="leu/i", lowtxt="ban/i",
divisor=100, jointxt="și", longval=longval)
return result.replace(
"unu leu", "un leu"
).replace("unu ban", "un ban")
def to_year(self, val, suffix=None, longval=True):
result = super(Num2Word_RO, self).to_year(
val,
longval=longval
)
# for years we want the era negation e.g. B.C., in our case
# it's î.Hr. or î.e.n
if result.startswith(self.negword):
result = result.replace(self.negword, "")
suffix = "î.Hr." if not suffix else suffix
if suffix:
result = "".join([
result,
" ",
suffix
])
return result

234
num2words/lang_RU.py Normal file
View File

@ -0,0 +1,234 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from .base import Num2Word_Base
from .utils import get_digits, splitbyx
ZERO = ('ноль',)
ONES_FEMININE = {
1: ('одна',),
2: ('две',),
3: ('три',),
4: ('четыре',),
5: ('пять',),
6: ('шесть',),
7: ('семь',),
8: ('восемь',),
9: ('девять',),
}
ONES = {
1: ('один',),
2: ('два',),
3: ('три',),
4: ('четыре',),
5: ('пять',),
6: ('шесть',),
7: ('семь',),
8: ('восемь',),
9: ('девять',),
}
TENS = {
0: ('десять',),
1: ('одиннадцать',),
2: ('двенадцать',),
3: ('тринадцать',),
4: ('четырнадцать',),
5: ('пятнадцать',),
6: ('шестнадцать',),
7: ('семнадцать',),
8: ('восемнадцать',),
9: ('девятнадцать',),
}
TWENTIES = {
2: ('двадцать',),
3: ('тридцать',),
4: ('сорок',),
5: ('пятьдесят',),
6: ('шестьдесят',),
7: ('семьдесят',),
8: ('восемьдесят',),
9: ('девяносто',),
}
HUNDREDS = {
1: ('сто',),
2: ('двести',),
3: ('триста',),
4: ('четыреста',),
5: ('пятьсот',),
6: ('шестьсот',),
7: ('семьсот',),
8: ('восемьсот',),
9: ('девятьсот',),
}
THOUSANDS = {
1: ('тысяча', 'тысячи', 'тысяч'), # 10^3
2: ('миллион', 'миллиона', 'миллионов'), # 10^6
3: ('миллиард', 'миллиарда', 'миллиардов'), # 10^9
4: ('триллион', 'триллиона', 'триллионов'), # 10^12
5: ('квадриллион', 'квадриллиона', 'квадриллионов'), # 10^15
6: ('квинтиллион', 'квинтиллиона', 'квинтиллионов'), # 10^18
7: ('секстиллион', 'секстиллиона', 'секстиллионов'), # 10^21
8: ('септиллион', 'септиллиона', 'септиллионов'), # 10^24
9: ('октиллион', 'октиллиона', 'октиллионов'), # 10^27
10: ('нониллион', 'нониллиона', 'нониллионов'), # 10^30
}
class Num2Word_RU(Num2Word_Base):
CURRENCY_FORMS = {
'RUB': (
('рубль', 'рубля', 'рублей'), ('копейка', 'копейки', 'копеек')
),
'EUR': (
('евро', 'евро', 'евро'), ('цент', 'цента', 'центов')
),
'USD': (
('доллар', 'доллара', 'долларов'), ('цент', 'цента', 'центов')
),
}
def setup(self):
self.negword = "минус"
self.pointword = "запятая"
self.ords = {"ноль": "нулевой",
"один": "первый",
"два": "второй",
"три": "третий",
"четыре": "четвертый",
"пять": "пятый",
"шесть": "шестой",
"семь": "седьмой",
"восемь": "восьмой",
"девять": "девятый",
"сто": "сотый"}
self.ords_feminine = {"один": "",
"одна": "",
"две": "двух",
"три": "трёх",
"четыре": "четырёх",
"пять": "пяти",
"шесть": "шести",
"семь": "семи",
"восемь": "восьми",
"девять": "девяти"}
def to_cardinal(self, number):
n = str(number).replace(',', '.')
if '.' in n:
left, right = n.split('.')
return u'%s %s %s' % (
self._int2word(int(left)),
self.pointword,
self._int2word(int(right))
)
else:
return self._int2word(int(n))
def pluralize(self, n, forms):
if n % 100 < 10 or n % 100 > 20:
if n % 10 == 1:
form = 0
elif 5 > n % 10 > 1:
form = 1
else:
form = 2
else:
form = 2
return forms[form]
def to_ordinal(self, number):
self.verify_ordinal(number)
outwords = self.to_cardinal(number).split(" ")
lastword = outwords[-1].lower()
try:
if len(outwords) > 1:
if outwords[-2] in self.ords_feminine:
outwords[-2] = self.ords_feminine.get(
outwords[-2], outwords[-2])
elif outwords[-2] == 'десять':
outwords[-2] = outwords[-2][:-1] + 'и'
if len(outwords) == 3:
if outwords[-3] in ['один', 'одна']:
outwords[-3] = ''
lastword = self.ords[lastword]
except KeyError:
if lastword[:-3] in self.ords_feminine:
lastword = self.ords_feminine.get(
lastword[:-3], lastword) + "сотый"
elif lastword[-1] == "ь" or lastword[-2] == "т":
lastword = lastword[:-1] + "ый"
elif lastword[-1] == "к":
lastword = lastword + "овой"
elif lastword[-5:] == "десят":
lastword = lastword.replace('ь', 'и') + 'ый'
elif lastword[-2] == "ч" or lastword[-1] == "ч":
if lastword[-2] == "ч":
lastword = lastword[:-1] + "ный"
if lastword[-1] == "ч":
lastword = lastword + "ный"
elif lastword[-1] == "н" or lastword[-2] == "н":
lastword = lastword[:lastword.rfind('н') + 1] + "ный"
elif lastword[-1] == "д" or lastword[-2] == "д":
lastword = lastword[:lastword.rfind('д') + 1] + "ный"
outwords[-1] = self.title(lastword)
return " ".join(outwords).strip()
def _cents_verbose(self, number, currency):
return self._int2word(number, currency == 'RUB')
def _int2word(self, n, feminine=False):
if n < 0:
return ' '.join([self.negword, self._int2word(abs(n))])
if n == 0:
return ZERO[0]
words = []
chunks = list(splitbyx(str(n), 3))
i = len(chunks)
for x in chunks:
i -= 1
if x == 0:
continue
n1, n2, n3 = get_digits(x)
if n3 > 0:
words.append(HUNDREDS[n3][0])
if n2 > 1:
words.append(TWENTIES[n2][0])
if n2 == 1:
words.append(TENS[n1][0])
elif n1 > 0:
ones = ONES_FEMININE if i == 1 or feminine and i == 0 else ONES
words.append(ones[n1][0])
if i > 0:
words.append(self.pluralize(x, THOUSANDS[i]))
return ' '.join(words)

141
num2words/lang_SL.py Normal file
View File

@ -0,0 +1,141 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# Copyright (c) 2015, Blaz Bregar. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from .lang_EU import Num2Word_EU
class Num2Word_SL(Num2Word_EU):
GIGA_SUFFIX = "iljard"
MEGA_SUFFIX = "iljon"
def setup(self):
super(Num2Word_SL, self).setup()
self.negword = "minus "
self.pointword = "celih"
self.errmsg_nonnum = "Only numbers may be converted to words."
self.errmsg_toobig = "Number is too large to convert to words."
self.exclude_title = []
self.mid_numwords = [(1000, "tisoč"), (900, "devetsto"),
(800, "osemsto"), (700, "sedemsto"),
(600, "šesto"), (500, "petsto"),
(400, "štiristo"), (300, "tristo"),
(200, "dvesto"), (100, "sto"),
(90, "devetdeset"), (80, "osemdeset"),
(70, "sedemdeset"), (60, "šestdeset"),
(50, "petdeset"), (40, "štirideset"),
(30, "trideset")]
self.low_numwords = ["dvajset", "devetnajst", "osemnajst",
"sedemnajst", "šestnajst", "petnajst",
"štirinajst", "trinajst", "dvanajst",
"enajst", "deset", "devet", "osem", "sedem",
"šest", "pet", "štiri", "tri", "dve", "ena",
"nič"]
self.ords = {"ena": "prv",
"dve": "drug",
"tri": "tretj",
"štiri": "četrt",
"sedem": "sedm",
"osem": "osm",
"sto": "stot",
"tisoč": "tisoč",
"miljon": "miljont"
}
self.ordflag = False
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if ctext == "dve" and not self.ordflag:
ctext = "dva"
if cnum == 1:
if nnum < 10**6 or self.ordflag:
return next
ctext = ""
if nnum > cnum:
if nnum >= 10**6:
if self.ordflag:
ntext += "t"
elif cnum == 2:
if ntext.endswith("d"):
ntext += "i"
else:
ntext += "a"
elif 2 < cnum < 5:
if ntext.endswith("d"):
ntext += "e"
elif not ntext.endswith("d"):
ntext += "i"
else:
if ntext.endswith("d"):
ntext += ""
elif ntext.endswith("d"):
ntext += "e"
else:
ntext += "ov"
if nnum >= 10**2 and self.ordflag is False:
ctext += " "
val = cnum * nnum
else:
if nnum < 10 < cnum < 100:
ntext, ctext = ctext, ntext + "in"
elif cnum >= 10**2 and self.ordflag is False:
ctext += " "
val = cnum + nnum
word = ctext + ntext
return (word, val)
def to_ordinal(self, value):
self.verify_ordinal(value)
self.ordflag = True
outword = self.to_cardinal(value)
self.ordflag = False
for key in self.ords:
if outword.endswith(key):
outword = outword[:len(outword) - len(key)] + self.ords[key]
break
return outword + "i"
# Is this correct??
def to_ordinal_num(self, value):
self.verify_ordinal(value)
return str(value) + "."
def to_currency(self, val, longval=True, old=False):
if old:
return self.to_splitnum(val, hightxt="evro/a/v",
lowtxt="stotin/a/i/ov",
jointxt="in", longval=longval)
return super(Num2Word_SL, self).to_currency(val, jointxt="in",
longval=longval)
def to_year(self, val, longval=True):
if not (val//100) % 10:
return self.to_cardinal(val)
return self.to_splitnum(val, hightxt="hundert", longval=longval)

216
num2words/lang_SR.py Normal file
View File

@ -0,0 +1,216 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from .base import Num2Word_Base
from .currency import parse_currency_parts, prefix_currency
from .utils import get_digits, splitbyx
ZERO = ('nula',)
ONES = {
1: ('jedan', 'jedna'),
2: ('dva', 'dve'),
3: ('tri', 'tri'),
4: ('četiri', 'četiri'),
5: ('pet', 'pet'),
6: ('šest', 'šest'),
7: ('sedam', 'sedam'),
8: ('osam', 'osam'),
9: ('devet', 'devet'),
}
TENS = {
0: ('deset',),
1: ('jedanaest',),
2: ('dvanaest',),
3: ('trinaest',),
4: ('četrnaest',),
5: ('petnaest',),
6: ('šesnaest',),
7: ('sedamnaest',),
8: ('osamnaest',),
9: ('devetnaest',),
}
TWENTIES = {
2: ('dvadeset',),
3: ('trideset',),
4: ('četrdeset',),
5: ('pedeset',),
6: ('šezdeset',),
7: ('sedamdeset',),
8: ('osamdeset',),
9: ('devedeset',),
}
HUNDREDS = {
1: ('sto',),
2: ('dvesta',),
3: ('trista',),
4: ('četristo',),
5: ('petsto',),
6: ('šesto',),
7: ('sedamsto',),
8: ('osamsto',),
9: ('devetsto',),
}
SCALE = {
0: ('', '', '', False),
1: ('hiljada', 'hiljade', 'hiljada', True), # 10^3
2: ('milion', 'miliona', 'miliona', False), # 10^6
3: ('bilion', 'biliona', 'biliona', False), # 10^9
4: ('trilion', 'triliona', 'triliona', False), # 10^12
5: ('kvadrilion', 'kvadriliona', 'kvadriliona', False), # 10^15
6: ('kvintilion', 'kvintiliona', 'kvintiliona', False), # 10^18
7: ('sekstilion', 'sekstiliona', 'sekstiliona', False), # 10^21
8: ('septilion', 'septiliona', 'septiliona', False), # 10^24
9: ('oktilion', 'oktiliona', 'oktiliona', False), # 10^27
10: ('nonilion', 'noniliona', 'noniliona', False), # 10^30
}
class Num2Word_SR(Num2Word_Base):
CURRENCY_FORMS = {
'RUB': (
('rublja', 'rublje', 'rublji', True),
('kopejka', 'kopejke', 'kopejki', True)
),
'EUR': (
('evro', 'evra', 'evra', False),
('cent', 'centa', 'centi', False)
),
'RSD': (
('dinar', 'dinara', 'dinara', False),
('para', 'pare', 'para', True)
),
}
def setup(self):
self.negword = "minus"
self.pointword = "zapeta"
def to_cardinal(self, number, feminine=False):
n = str(number).replace(',', '.')
if '.' in n:
left, right = n.split('.')
return u'%s %s %s' % (
self._int2word(int(left), feminine),
self.pointword,
self._int2word(int(right), feminine)
)
else:
return self._int2word(int(n), feminine)
def pluralize(self, number, forms):
if number % 100 < 10 or number % 100 > 20:
if number % 10 == 1:
form = 0
elif 1 < number % 10 < 5:
form = 1
else:
form = 2
else:
form = 2
return forms[form]
def to_ordinal(self, number):
raise NotImplementedError()
def _cents_verbose(self, number, currency):
return self._int2word(
number,
self.CURRENCY_FORMS[currency][1][-1]
)
def _int2word(self, number, feminine=False):
if number < 0:
return ' '.join([self.negword, self._int2word(abs(number))])
if number == 0:
return ZERO[0]
words = []
chunks = list(splitbyx(str(number), 3))
chunk_len = len(chunks)
for chunk in chunks:
chunk_len -= 1
digit_right, digit_mid, digit_left = get_digits(chunk)
if digit_left > 0:
words.append(HUNDREDS[digit_left][0])
if digit_mid > 1:
words.append(TWENTIES[digit_mid][0])
if digit_mid == 1:
words.append(TENS[digit_right][0])
elif digit_right > 0:
is_feminine = feminine or SCALE[chunk_len][-1]
gender_idx = int(is_feminine)
words.append(
ONES[digit_right][gender_idx]
)
if chunk_len > 0 and chunk != 0:
words.append(self.pluralize(chunk, SCALE[chunk_len]))
return ' '.join(words)
def to_currency(self, val, currency='EUR', cents=True, seperator=',',
adjective=False):
"""
Args:
val: Numeric value
currency (str): Currency code
cents (bool): Verbose cents
seperator (str): Cent seperator
adjective (bool): Prefix currency name with adjective
Returns:
str: Formatted string
"""
left, right, is_negative = parse_currency_parts(val)
try:
cr1, cr2 = self.CURRENCY_FORMS[currency]
except KeyError:
raise NotImplementedError(
'Currency code "%s" not implemented for "%s"' %
(currency, self.__class__.__name__))
if adjective and currency in self.CURRENCY_ADJECTIVES:
cr1 = prefix_currency(
self.CURRENCY_ADJECTIVES[currency],
cr1
)
minus_str = "%s " % self.negword if is_negative else ""
cents_str = self._cents_verbose(right, currency) \
if cents else self._cents_terse(right, currency)
return u'%s%s %s%s %s %s' % (
minus_str,
self.to_cardinal(left, feminine=cr1[-1]),
self.pluralize(left, cr1),
seperator,
cents_str,
self.pluralize(right, cr2)
)

183
num2words/lang_TH.py Normal file
View File

@ -0,0 +1,183 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from num2words.base import Num2Word_Base
from num2words.currency import parse_currency_parts
from num2words.utils import splitbyx
class Num2Word_TH(Num2Word_Base):
def setup(self):
self.negword = 'ติดลบ'
self.pointword = 'จุด'
self.CURRENCY_FORMS = {
'THB': (('บาท', 'บาท'), ('สตางค์', 'สตางค์')),
'USD': (('ดอลลาร์', 'ดอลลาร์'), ('เซนต์', 'เซนต์')),
'EUR': (('ยูโร', 'ยูโร'), ('เซนต์', 'เซนต์')),
}
self.high_numwords = []
self.mid_numwords = ['', 'สิบ', 'ร้อย', 'พัน', 'หมื่น', 'แสน', 'ล้าน']
self.low_numwords = [
'ศูนย์', 'หนึ่ง', 'สอง', 'สาม', 'สี่',
'ห้า', 'หก', 'เจ็ด', 'แปด', 'เก้า'
]
def set_high_numwords(self, high_numwords):
pass
def set_mid_numwords(self, mid_numwords):
pass
def splitnum(self, six_num):
length = len(six_num) > 1
word_num = ''
for index, num in enumerate(map(int, six_num)):
if num:
if index:
word_num = self.mid_numwords[index] + word_num
if length and num == 1 and index == 0:
word_num += 'เอ็ด'
elif index == 1 and num == 2:
word_num = 'ยี่' + word_num
elif index != 1 or num != 1:
word_num = self.low_numwords[num] + word_num
elif num == 0 and index == 0 and length == 0:
word_num = self.low_numwords[0]
return word_num
def split_six(self, num_txt):
result = splitbyx(num_txt, 6, format_int=False)
result = list(result)[::-1]
number_list = []
for i in result:
number_list.append(i[::-1])
return number_list
def add_text_million(self, word_num):
result = ''
for index, t in enumerate(reversed(word_num)):
if index == 0:
result = t
else:
result = result + 'ล้าน' + t
return result
def round_2_decimal(self, number):
integer, cents, negative = parse_currency_parts(
number, is_int_with_cents=False
)
integer = '{}'.format(integer)
cents = '{}'.format(cents)
if len(cents) < 2:
add_zero = 2 - len(cents)
cents = ('0' * add_zero) + cents
text_num = integer + '.' + cents
return text_num, negative
def left_num_to_text(self, number):
left_num_list = self.split_six(number)
left_text_list = []
for i in left_num_list:
left_text_list.append(self.splitnum(i))
left_text = self.add_text_million(left_text_list)
return left_text
def to_cardinal(self, number):
negative = number < 0
pre, post = self.float2tuple(number)
precision = self.precision
pre = '{}'.format(pre)
post = '{}'.format(post)
if negative:
pre = pre.lstrip('-')
if len(post) < precision:
add_zero = precision - len(post)
post = ('0' * add_zero) + post
result = self.left_num_to_text(pre)
right_text = ''
if not post == '0':
for i in map(int, post):
right_text = right_text + self.low_numwords[i]
result = result + 'จุด' + right_text
if negative:
result = 'ติดลบ' + result
return result
def to_ordinal(self, number):
return self.to_cardinal(number)
def to_currency(self, number, currency='THB'):
number, negative = self.round_2_decimal(number)
split_num = number.split('.')
left_num = split_num[0]
left_text = self.left_num_to_text(left_num)
right_num = split_num[1]
right_text = self.splitnum(right_num[::-1].rstrip('0'))
try:
cr1, cr2 = self.CURRENCY_FORMS[currency]
except KeyError:
raise NotImplementedError(
'Currency code "%s" not implemented for "%s"' %
(currency, self.__class__.__name__))
if right_num == '00':
if currency == 'THB':
result = left_text + cr1[0] + 'ถ้วน'
else:
result = left_text + cr1[0]
else:
if left_num == '0':
result = right_text + cr2[0]
else:
result = left_text + cr1[0] + right_text + cr2[0]
if negative:
result = self.negword + result
return result

838
num2words/lang_TR.py Normal file
View File

@ -0,0 +1,838 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# Copyright (c) 2017, Tufan Kaynak, Framras. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
class Num2Word_TR(object):
def __init__(self):
self.precision = 2
self.negword = u"eksi"
self.pointword = u"virgül"
self.CURRENCY_UNIT = (u"lira",)
self.CURRENCY_SUBUNIT = (u"kuruş",)
self.errmsg_nonnum = u"Sadece sayılar yazıya çevrilebilir."
self.errmsg_floatord = u"Tam sayı olmayan {} sıralamada kullanılamaz."
self.errmsg_negord = u"Pozitif olmayan {} sıralamada kullanılamaz."
self.errmsg_toobig = u"abs({}) sayı yazıya çevirmek için çok büyük. " \
u"Yazıya çevrilebilecek en büyük rakam {}."
self.exclude_title = []
self.DECIMAL_SIGN = (",",)
self.ORDINAL_SIGN = (".",)
self.ZERO = (u"sıfır",)
self.CARDINAL_ONES = {
"1": u"bir",
"2": u"iki",
"3": u"üç",
"4": u"dört",
"5": u"beş",
"6": u"altı",
"7": u"yedi",
"8": u"sekiz",
"9": u"dokuz"
}
self.ORDINAL_ONES = {
"1": u"birinci",
"2": u"ikinci",
"3": u"üçüncü",
"4": u"dördüncü",
"5": u"beşinci",
"6": u"altıncı",
"7": u"yedinci",
"8": u"sekizinci",
"9": u"dokuzuncu"
}
self.CARDINAL_TENS = {
"1": u"on",
"2": u"yirmi",
"3": u"otuz",
"4": u"kırk",
"5": u"elli",
"6": u"altmış",
"7": u"yetmiş",
"8": u"seksen",
"9": u"doksan"
}
self.ORDINAL_TENS = {
"1": u"onuncu",
"2": u"yirminci",
"3": u"otuzuncu",
"4": u"kırkıncı",
"5": u"ellinci",
"6": u"altmışıncı",
"7": u"yetmişinci",
"8": u"sekseninci",
"9": u"doksanıncı"
}
self.HUNDREDS = {
"2": u"iki",
"3": u"üç",
"4": u"dört",
"5": u"beş",
"6": u"altı",
"7": u"yedi",
"8": u"sekiz",
"9": u"dokuz"
}
self.CARDINAL_HUNDRED = (u"yüz",)
self.ORDINAL_HUNDRED = (u"yüzüncü",)
self.CARDINAL_TRIPLETS = {
1: u"bin",
2: u"milyon",
3: u"milyar",
4: u"trilyon",
5: u"katrilyon",
6: u"kentilyon"
}
self.ORDINAL_TRIPLETS = {
1: u"bininci",
2: u"milyonuncu",
3: u"milyarıncı",
4: u"trilyonuncu",
5: u"katrilyonuncu",
6: u"kentilyon"
}
self.MAXVAL = (10 ** ((len(self.CARDINAL_TRIPLETS) + 1) * 3)) - 1
self.integers_to_read = []
self.total_triplets_to_read = 0
self.total_digits_outside_triplets = 0
self.order_of_last_zero_digit = 0
def to_cardinal(self, value):
wrd = ""
is_cardinal = self.verify_cardinal(value)
if not is_cardinal:
return wrd
if not int(value) == value:
return self.to_cardinal_float(value)
self.to_splitnum(value)
if self.order_of_last_zero_digit >= len(self.integers_to_read[0]):
# number like 00 and all 0s and even more, raise error
return wrd
if self.total_triplets_to_read == 1:
if self.total_digits_outside_triplets == 2:
if self.order_of_last_zero_digit == 1:
# number like x0, read cardinal x0 and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
return wrd
if self.order_of_last_zero_digit == 0:
# number like xy, read cardinal xy and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][1], ""
)
return wrd
if self.total_digits_outside_triplets == 1:
if self.order_of_last_zero_digit == 0:
# number like x, read cardinal x and return
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][0], ""
)
return wrd
if self.total_digits_outside_triplets == 0:
if self.order_of_last_zero_digit == 2:
# number like x00, read cardinal x00 and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
return wrd
if self.order_of_last_zero_digit == 1:
# number like xy0, read cardinal xy0 and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
return wrd
if self.order_of_last_zero_digit == 0:
# number like xyz, read cardinal xyz and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][2], ""
)
return wrd
if self.total_triplets_to_read >= 2:
if self.total_digits_outside_triplets == 2:
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 1:
# number like x0 and all 0s, read cardinal x0 0..0
# and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 2:
# number like xy and all 0s, read cardinal xy 0..0
# and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][1], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit < len(
self.integers_to_read[0]) - 2:
# number like xy and others, read cardinal xy n..n
# and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][1], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
if self.total_digits_outside_triplets == 1:
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 1:
# number like x and all 0s, read cardinal x 0..0
# and return
if not (self.total_triplets_to_read == 2 and
self.integers_to_read[0][0] == "1"):
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit < len(
self.integers_to_read[0]) - 1:
# number like x and others, read cardinal x n..n
# and return
if not (self.total_triplets_to_read == 2 and
self.integers_to_read[0][0] == "1"):
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
if self.total_digits_outside_triplets == 0:
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 1:
# number like x00 and all 0s, read cardinal x00 0..0
# and return
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 2:
# number like xy0 and all 0s, read cardinal xy0 0..0
# and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 3:
# number like xyz and all 0s, read cardinal xyz 0..0
# and return
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][2], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit < len(
self.integers_to_read[0]) - 3:
# number like xyz and all others, read cardinal xyz n..n
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
if not (self.total_triplets_to_read == 2 and
self.integers_to_read[0][2] == "1"):
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][2], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
for i in list(range(self.total_triplets_to_read - 1, 0, -1)):
reading_triplet_order = self.total_triplets_to_read - i
if self.total_digits_outside_triplets == 0:
last_read_digit_order = reading_triplet_order * 3
else:
last_read_digit_order = (reading_triplet_order - 1) * 3 +\
self.total_digits_outside_triplets
if not self.integers_to_read[0][
last_read_digit_order: last_read_digit_order + 3
] == "000":
if not self.integers_to_read[0][
last_read_digit_order
] == "0":
wrd += self.HUNDREDS.get(
self.integers_to_read[0][last_read_digit_order], ""
)
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - (
last_read_digit_order) - 1:
if i == 1:
wrd += self.CARDINAL_HUNDRED[0]
return wrd
elif i > 1:
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TRIPLETS[i - 1]
return wrd
else:
wrd += self.CARDINAL_HUNDRED[0]
if not self.integers_to_read[0][
last_read_digit_order + 1] == "0":
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - (
last_read_digit_order) - 2:
if i == 1:
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][
last_read_digit_order + 1], ""
)
return wrd
elif i > 1:
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][
last_read_digit_order + 1], ""
)
wrd += self.CARDINAL_TRIPLETS[i - 1]
return wrd
else:
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][
last_read_digit_order + 1], ""
)
if not self.integers_to_read[0][
last_read_digit_order + 2] == "0":
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - (
last_read_digit_order) - 3:
if i == 1:
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
return wrd
if i == 2:
if not self.integers_to_read[0][
last_read_digit_order:
last_read_digit_order + 2
] == "00":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
elif not self.integers_to_read[0][
last_read_digit_order + 2] == "1":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
wrd += self.CARDINAL_TRIPLETS[i - 1]
return wrd
if i > 2:
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
wrd += self.CARDINAL_TRIPLETS[i - 1]
return wrd
else:
if not self.integers_to_read[0][
last_read_digit_order:
last_read_digit_order + 2
] == "00":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
else:
if i == 2:
if not self.integers_to_read[0][
last_read_digit_order:
last_read_digit_order + 2
] == "00":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
elif not self.integers_to_read[0][
last_read_digit_order + 2
] == "1":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
wrd += self.CARDINAL_TRIPLETS[i - 1]
return wrd
def to_cardinal_float(self, value):
self.to_splitnum(value)
wrd = ""
wrd += self.pointword
if len(self.integers_to_read[1]) >= 1:
wrd += self.CARDINAL_TENS.get(self.integers_to_read[1][0], "")
if len(self.integers_to_read[1]) == 2:
wrd += self.CARDINAL_ONES.get(self.integers_to_read[1][1], "")
if self.integers_to_read[0] == "0":
wrd = self.ZERO[0] + wrd
else:
wrd = self.to_cardinal(int(self.integers_to_read[0])) + wrd
return wrd
def verify_cardinal(self, value):
iscardinal = True
try:
if not float(value) == value:
iscardinal = False
except (ValueError, TypeError):
raise TypeError(self.errmsg_nonnum)
if abs(value) >= self.MAXVAL:
raise OverflowError(self.errmsg_toobig.format(value, self.MAXVAL))
return iscardinal
def verify_ordinal(self, value):
isordinal = True
try:
if not int(value) == value:
isordinal = False
if not abs(value) == value:
raise TypeError(self.errmsg_negord.format(value))
except (ValueError, TypeError):
raise TypeError(self.errmsg_nonnum)
if abs(value) >= self.MAXVAL:
raise OverflowError(self.errmsg_toobig.format(value, self.MAXVAL))
return isordinal
def to_ordinal(self, value):
wrd = ""
isordinal = self.verify_ordinal(value)
if isordinal:
self.to_splitnum(value)
if self.order_of_last_zero_digit >= len(self.integers_to_read[0]):
# number like 00 and all 0s and even more, raise error
return wrd
if self.total_triplets_to_read == 1:
if self.total_digits_outside_triplets == 2:
if self.order_of_last_zero_digit == 1:
# number like x0, read ordinal x0 and return
wrd += self.ORDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
return wrd
if self.order_of_last_zero_digit == 0:
# number like xy, read ordinal xy and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
wrd += self.ORDINAL_ONES.get(
self.integers_to_read[0][1], ""
)
return wrd
if self.total_digits_outside_triplets == 1:
if self.order_of_last_zero_digit == 0:
# number like x, read ordinal x and return
wrd += self.ORDINAL_ONES.get(
self.integers_to_read[0][0], ""
)
return wrd
if self.total_digits_outside_triplets == 0:
if self.order_of_last_zero_digit == 2:
# number like x00, read ordinal x00 and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.ORDINAL_HUNDRED[0]
return wrd
if self.order_of_last_zero_digit == 1:
# number like xy0, read ordinal xy0 and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.ORDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
return wrd
if self.order_of_last_zero_digit == 0:
# number like xyz, read ordinal xyz and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
if not self.integers_to_read[0][2] == "0":
wrd += self.ORDINAL_ONES.get(
self.integers_to_read[0][2], ""
)
return wrd
if self.total_triplets_to_read >= 2:
if self.total_digits_outside_triplets == 2:
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 1:
# number like x0 and all 0s, read ordinal x0 0..0
# and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
wrd += self.ORDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 2:
# number like xy and all 0s, read ordinal xy 0..0
# and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][1], ""
)
wrd += self.ORDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit < len(
self.integers_to_read[0]) - 2:
# number like xy and others, read cardinal xy n..n
# and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][1], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
if self.total_digits_outside_triplets == 1:
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 1:
# number like x and all 0s, read ordinal x 0..0
# and return
if not (self.total_triplets_to_read == 2 and
self.integers_to_read[0][0] == "1"):
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][0], ""
)
wrd += self.ORDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit < len(
self.integers_to_read[0]) - 1:
# number like x and others, read cardinal x n..n
# and return
if not (self.total_triplets_to_read == 2 and
self.integers_to_read[0][0] == "1"):
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
if self.total_digits_outside_triplets == 0:
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 1:
# number like x00 and all 0s, read ordinal x00 0..0
# and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.ORDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 2:
# number like xy0 and all 0s, read ordinal xy0 0..0
# and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
wrd += self.ORDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 3:
# number like xyz and all 0s, read ordinal xyz 0..0
# and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][2], ""
)
wrd += self.ORDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit < len(
self.integers_to_read[0]) - 3:
# number like xyz and all others, read cardinal
# xyz n..n
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
if not (self.total_triplets_to_read == 2 and
self.integers_to_read[0][2] == "1"):
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][2], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
for i in list(range(self.total_triplets_to_read - 1, 0, -1)):
reading_triplet_order = self.total_triplets_to_read - i
if self.total_digits_outside_triplets == 0:
last_read_digit_order = reading_triplet_order * 3
else:
last_read_digit_order = \
(reading_triplet_order - 1) * 3 + \
self.total_digits_outside_triplets
if not self.integers_to_read[0][
last_read_digit_order: last_read_digit_order + 3
] == "000":
if not self.integers_to_read[0][
last_read_digit_order
] == "0":
if not self.integers_to_read[0][
last_read_digit_order
] == "1":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order
], ""
)
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - (
last_read_digit_order) - 1:
if i == 1:
wrd += self.ORDINAL_HUNDRED[0]
return wrd
elif i > 1:
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.ORDINAL_TRIPLETS[i - 1]
return wrd
else:
wrd += self.CARDINAL_HUNDRED[0]
if not self.integers_to_read[0][
last_read_digit_order + 1
] == "0":
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - (
last_read_digit_order) - 2:
if i == 1:
wrd += self.ORDINAL_TENS.get(
self.integers_to_read[0][
last_read_digit_order + 1], ""
)
return wrd
elif i > 1:
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][
last_read_digit_order + 1], ""
)
wrd += self.ORDINAL_TRIPLETS[i - 1]
return wrd
else:
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][
last_read_digit_order + 1], ""
)
if not self.integers_to_read[0][
last_read_digit_order + 2
] == "0":
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - (
last_read_digit_order) - 3:
if i == 1:
wrd += self.ORDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
return wrd
if i == 2:
if not self.integers_to_read[0][
last_read_digit_order:
last_read_digit_order + 2] == "00":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
elif not self.integers_to_read[0][
last_read_digit_order + 2
] == "1":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
wrd += self.ORDINAL_TRIPLETS[i - 1]
return wrd
if i > 2:
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
wrd += self.ORDINAL_TRIPLETS[i - 1]
return wrd
else:
if not self.integers_to_read[0][
last_read_digit_order:
last_read_digit_order + 2] == "00":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
else:
if not self.integers_to_read[0][
last_read_digit_order:
last_read_digit_order + 2] == "00":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
elif not self.integers_to_read[0][
last_read_digit_order + 2] == "1":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
wrd += self.CARDINAL_TRIPLETS[i - 1]
return wrd
def to_splitnum(self, val):
float_digits = str(int(val * 10 ** self.precision))
if not int(val) == 0:
self.integers_to_read = [
str(int(val)),
float_digits[len(float_digits) - self.precision:]
]
else:
self.integers_to_read = [
"0",
"0" * (self.precision - len(float_digits)) +
float_digits[len(float_digits) - self.precision:]
]
if len(self.integers_to_read[0]) % 3 > 0:
self.total_triplets_to_read = (len(self.integers_to_read[0]) // 3)\
+ 1
elif len(self.integers_to_read[0]) % 3 == 0:
self.total_triplets_to_read = len(self.integers_to_read[0]) // 3
self.total_digits_outside_triplets = len(self.integers_to_read[0]) % 3
okunacak = list(self.integers_to_read[0][::-1])
self.order_of_last_zero_digit = 0
found = 0
for i in range(len(okunacak) - 1):
if int(okunacak[i]) == 0 and found == 0:
self.order_of_last_zero_digit = i + 1
else:
found = 1
def to_currency(self, value):
valueparts = self.to_cardinal(value).split(self.pointword)
if len(valueparts) == 1:
return valueparts[0] + self.CURRENCY_UNIT[0]
if len(valueparts) == 2:
return self.CURRENCY_UNIT[0].join(valueparts) + \
self.CURRENCY_SUBUNIT[0]

179
num2words/lang_UK.py Normal file
View File

@ -0,0 +1,179 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from .base import Num2Word_Base
from .utils import get_digits, splitbyx
ZERO = ('нуль',)
ONES_FEMININE = {
1: ('одна',),
2: ('двi',),
3: ('три',),
4: ('чотири',),
5: ('п\'ять',),
6: ('шiсть',),
7: ('с',),
8: ('вiс',),
9: ('дев\'ять',),
}
ONES = {
1: ('один',),
2: ('два',),
3: ('три',),
4: ('чотири',),
5: ('п\'ять',),
6: ('шiсть',),
7: ('с',),
8: ('вiс',),
9: ('дев\'ять',),
}
TENS = {
0: ('десять',),
1: ('одинадцять',),
2: ('дванадцять',),
3: ('тринадцять',),
4: ('чотирнадцять',),
5: ('п\'ятнадцять',),
6: ('шiстнадцять',),
7: ('сiмнадцять',),
8: ('вiсiмнадцять',),
9: ('дев\'ятнадцять',),
}
TWENTIES = {
2: ('двадцять',),
3: ('тридцять',),
4: ('сорок',),
5: ('п\'ятдесят',),
6: ('шiстдесят',),
7: ('сiмдесят',),
8: ('вiсiмдесят',),
9: ('дев\'яносто',),
}
HUNDREDS = {
1: ('сто',),
2: ('двiстi',),
3: ('триста',),
4: ('чотириста',),
5: ('п\'ятсот',),
6: ('шiстсот',),
7: ('ссот',),
8: ('вiссот',),
9: ('дев\'ятсот',),
}
THOUSANDS = {
1: ('тисяча', 'тисячi', 'тисяч'), # 10^3
2: ('мiльйон', 'мiльйони', 'мiльйонiв'), # 10^6
3: ('мiльярд', 'мiльярди', 'мiльярдiв'), # 10^9
4: ('трильйон', 'трильйони', 'трильйонiв'), # 10^12
5: ('квадрильйон', 'квадрильйони', 'квадрильйонiв'), # 10^15
6: ('квiнтильйон', 'квiнтильйони', 'квiнтильйонiв'), # 10^18
7: ('секстильйон', 'секстильйони', 'секстильйонiв'), # 10^21
8: ('септильйон', 'септильйони', 'септильйонiв'), # 10^24
9: ('октильйон', 'октильйони', 'октильйонiв'), # 10^27
10: ('нонiльйон', 'нонiльйони', 'нонiльйонiв'), # 10^30
}
class Num2Word_UK(Num2Word_Base):
CURRENCY_FORMS = {
'UAH': (
('гривня', 'гривнi', 'гривень'),
('копiйка', 'копiйки', 'копiйок')
),
'EUR': (
('євро', 'євро', 'євро'), ('цент', 'центи', 'центiв')
),
}
def setup(self):
self.negword = "мiнус"
self.pointword = "кома"
def to_cardinal(self, number):
n = str(number).replace(',', '.')
if '.' in n:
left, right = n.split('.')
return '%s %s %s' % (
self._int2word(int(left)),
self.pointword,
self._int2word(int(right))
)
else:
return self._int2word(int(n))
def pluralize(self, n, forms):
if n % 100 < 10 or n % 100 > 20:
if n % 10 == 1:
form = 0
elif 5 > n % 10 > 1:
form = 1
else:
form = 2
else:
form = 2
return forms[form]
def _int2word(self, n, feminine=True):
if n < 0:
return ' '.join([self.negword, self._int2word(abs(n))])
if n == 0:
return ZERO[0]
words = []
chunks = list(splitbyx(str(n), 3))
i = len(chunks)
for x in chunks:
i -= 1
if x == 0:
continue
n1, n2, n3 = get_digits(x)
if n3 > 0:
words.append(HUNDREDS[n3][0])
if n2 > 1:
words.append(TWENTIES[n2][0])
if n2 == 1:
words.append(TENS[n1][0])
# elif n1 > 0 and not (i > 0 and x == 1):
elif n1 > 0:
ones = ONES_FEMININE if i == 1 or feminine and i == 0 else ONES
words.append(ones[n1][0])
if i > 0:
words.append(self.pluralize(x, THOUSANDS[i]))
return ' '.join(words)
def _cents_verbose(self, number, currency):
return self._int2word(number, currency == 'UAH')
def to_ordinal(self, number):
raise NotImplementedError()

101
num2words/lang_VI.py Normal file
View File

@ -0,0 +1,101 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
to_19 = (u'không', u'một', u'hai', u'ba', u'bốn', u'năm', u'sáu',
u'bảy', u'tám', u'chín', u'mười', u'mười một', u'mười hai',
u'mười ba', u'mười bốn', u'mười lăm', u'mười sáu', u'mười bảy',
u'mười tám', u'mười chín')
tens = (u'hai mươi', u'ba mươi', u'bốn mươi', u'năm mươi',
u'sáu mươi', u'bảy mươi', u'tám mươi', u'chín mươi')
denom = ('',
u'nghìn', u'triệu', u'tỷ', u'nghìn tỷ', u'trăm nghìn tỷ',
'Quintillion', 'Sextillion', 'Septillion', 'Octillion', 'Nonillion',
'Decillion', 'Undecillion', 'Duodecillion', 'Tredecillion',
'Quattuordecillion', 'Sexdecillion', 'Septendecillion',
'Octodecillion', 'Novemdecillion', 'Vigintillion')
class Num2Word_VI(object):
def _convert_nn(self, val):
if val < 20:
return to_19[val]
for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens)):
if dval + 10 > val:
if val % 10:
a = u'lăm'
if to_19[val % 10] == u'một':
a = u'mốt'
else:
a = to_19[val % 10]
if to_19[val % 10] == u'năm':
a = u'lăm'
return dcap + ' ' + a
return dcap
def _convert_nnn(self, val):
word = ''
(mod, rem) = (val % 100, val // 100)
if rem > 0:
word = to_19[rem] + u' trăm'
if mod > 0:
word = word + ' '
if mod > 0 and mod < 10:
if mod == 5:
word = word != '' and word + u'lẻ năm' or word + u'năm'
else:
word = word != '' and word + u'lẻ ' \
+ self._convert_nn(mod) or word + self._convert_nn(mod)
if mod >= 10:
word = word + self._convert_nn(mod)
return word
def vietnam_number(self, val):
if val < 100:
return self._convert_nn(val)
if val < 1000:
return self._convert_nnn(val)
for (didx, dval) in ((v - 1, 1000 ** v) for v in range(len(denom))):
if dval > val:
mod = 1000 ** didx
lval = val // mod
r = val - (lval * mod)
ret = self._convert_nnn(lval) + u' ' + denom[didx]
if 99 >= r > 0:
ret = self._convert_nnn(lval) + u' ' + denom[didx] + u' lẻ'
if r > 0:
ret = ret + ' ' + self.vietnam_number(r)
return ret
def number_to_text(self, number):
number = '%.2f' % number
the_list = str(number).split('.')
start_word = self.vietnam_number(int(the_list[0]))
final_result = start_word
if len(the_list) > 1 and int(the_list[1]) > 0:
end_word = self.vietnam_number(int(the_list[1]))
final_result = final_result + ' phẩy ' + end_word
return final_result
def to_cardinal(self, number):
return self.number_to_text(number)
def to_ordinal(self, number):
return self.to_cardinal(number)

35
num2words/utils.py Normal file
View File

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
def splitbyx(n, x, format_int=True):
length = len(n)
if length > x:
start = length % x
if start > 0:
result = n[:start]
yield int(result) if format_int else result
for i in range(start, length, x):
result = n[i:i+x]
yield int(result) if format_int else result
else:
yield int(n) if format_int else n
def get_digits(n):
a = [int(x) for x in reversed(list(('%03d' % n)[-3:]))]
return a

6
requirements-test.txt Normal file
View File

@ -0,0 +1,6 @@
flake8
flake8-copyright
isort
pep8<1.6
coverage
delegator.py

79
setup.py Normal file
View File

@ -0,0 +1,79 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
import re
from io import open
from setuptools import find_packages, setup
PACKAGE_NAME = "num2words"
CLASSIFIERS = [
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU Library or Lesser General Public License '
'(LGPL)',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Topic :: Software Development :: Internationalization',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Software Development :: Localization',
'Topic :: Text Processing :: Linguistic',
]
LONG_DESC = open('README.rst', 'rt', encoding="utf-8").read() + '\n\n' + \
open('CHANGES.rst', 'rt', encoding="utf-8").read()
def find_version(fname):
"""Parse file & return version number matching 0.0.1 regex
Returns str or raises RuntimeError
"""
version = ''
with open(fname, 'r', encoding="utf-8") as fp:
reg = re.compile(r'__version__ = [\'"]([^\'"]*)[\'"]')
for line in fp:
m = reg.match(line)
if m:
version = m.group(1)
break
if not version:
raise RuntimeError('Cannot find version information')
return version
setup(
name=PACKAGE_NAME,
version=find_version("bin/num2words"),
description='Modules to convert numbers to words. Easily extensible.',
long_description=LONG_DESC,
license='LGPL',
author='Taro Ogawa <tso at users sourceforge net>',
author_email='tos@users.sourceforge.net',
maintainer='Savoir-faire Linux inc.',
maintainer_email='istvan.szalai@savoirfairelinux.com',
keywords=' number word numbers words convert conversion i18n '
'localisation localization internationalisation '
'internationalization',
url='https://github.com/savoirfairelinux/num2words',
packages=find_packages(exclude=['tests']),
test_suite='tests',
classifiers=CLASSIFIERS,
scripts=['bin/num2words'],
install_requires=["docopt>=0.6.2"],
tests_require=['delegator.py'],
)

0
tests/__init__.py Normal file
View File

113
tests/test_ar.py Normal file
View File

@ -0,0 +1,113 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from unittest import TestCase
from num2words import num2words
class Num2WordsARTest(TestCase):
def test_default_currency(self):
self.assertEqual(num2words(1, to='currency', lang='ar'), 'واحد ريال')
self.assertEqual(num2words(2, to='currency', lang='ar'),
'اثنان ريالان')
self.assertEqual(num2words(10, to='currency', lang='ar'),
'عشرة ريالات')
self.assertEqual(num2words(100, to='currency', lang='ar'), 'مائة ريال')
self.assertEqual(num2words(652.12, to='currency', lang='ar'),
'ستمائة و اثنان و خمسون ريالاً و اثنتا عشرة هللة')
self.assertEqual(num2words(324, to='currency', lang='ar'),
'ثلاثمائة و أربعة و عشرون ريالاً')
self.assertEqual(num2words(2000, to='currency', lang='ar'),
'ألفا ريال')
self.assertEqual(num2words(541, to='currency', lang='ar'),
'خمسمائة و واحد و أربعون ريالاً')
self.assertEqual(num2words(10000, to='currency', lang='ar'),
'عشرة آلاف ريال')
self.assertEqual(num2words(20000.12, to='currency', lang='ar'),
'عشرون ألف ريال و اثنتا عشرة هللة')
self.assertEqual(num2words(1000000, to='currency', lang='ar'),
'واحد مليون ريال')
val = 'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر ريالاً'
self.assertEqual(num2words(923411, to='currency', lang='ar'), val)
self.assertEqual(num2words(63411, to='currency', lang='ar'),
'ثلاثة و ستون ألفاً و أربعمائة و أحد عشر ريالاً')
self.assertEqual(num2words(1000000.99, to='currency', lang='ar'),
'واحد مليون ريال و تسع و تسعون هللة')
def test_currency_parm(self):
self.assertEqual(
num2words(1, to='currency', lang='ar', currency="KWD"),
'واحد دينار')
self.assertEqual(
num2words(10, to='currency', lang='ar', currency="EGP"),
'عشرة جنيهات')
self.assertEqual(
num2words(20000.12, to='currency', lang='ar', currency="EGP"),
'عشرون ألف جنيه و اثنتا عشرة قرش')
self.assertEqual(
num2words(923411, to='currency', lang='ar', currency="SR"),
'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر ريالاً')
self.assertEqual(
num2words(1000000.99, to='currency', lang='ar', currency="KWD"),
'واحد مليون دينار و تسع و تسعون فلس')
def test_ordinal(self):
self.assertEqual(num2words(1, to='ordinal', lang='ar'), 'اول')
self.assertEqual(num2words(2, to='ordinal', lang='ar'), 'ثاني')
self.assertEqual(num2words(3, to='ordinal', lang='ar'), 'ثالث')
self.assertEqual(num2words(4, to='ordinal', lang='ar'), 'رابع')
self.assertEqual(num2words(5, to='ordinal', lang='ar'), 'خامس')
self.assertEqual(num2words(6, to='ordinal', lang='ar'), 'سادس')
self.assertEqual(num2words(9, to='ordinal', lang='ar'), 'تاسع')
self.assertEqual(num2words(20, to='ordinal', lang='ar'), 'عشرون')
self.assertEqual(num2words(94, to='ordinal', lang='ar'),
'أربع و تسعون')
self.assertEqual(num2words(102, to='ordinal', lang='ar'),
'مائة و اثنان')
self.assertEqual(
num2words(923411, to='ordinal_num', lang='ar'),
'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر')
def test_cardinal(self):
self.assertEqual(num2words(12, to='cardinal', lang='ar'), 'اثنا عشر')
self.assertEqual(num2words(-8324, to='cardinal', lang='ar'),
'سالب ثمانية آلاف و ثلاثمائة و أربعة و عشرون')
self.assertEqual(
num2words(3431.12, to='cardinal', lang='ar'),
'ثلاثة آلاف و أربعمائة و واحد و ثلاثون , اثنتا عشرة')
self.assertEqual(num2words(431, to='cardinal', lang='ar'),
'أربعمائة و واحد و ثلاثون')
self.assertEqual(num2words(94231, to='cardinal', lang='ar'),
'أربعة و تسعون ألفاً و مئتان و واحد و ثلاثون')
self.assertEqual(num2words(1431, to='cardinal', lang='ar'),
'واحد ألف و أربعمائة و واحد و ثلاثون')
def test_prefix_and_suffix(self):
self.assertEqual(num2words(645, to='currency',
lang='ar', prefix="فقط", suffix="لاغير"),
'فقط ستمائة و خمسة و أربعون ريالاً لاغير')
def test_year(self):
self.assertEqual(num2words(2000, to='year', lang='ar'), 'ألفا')
def test_max_numbers(self):
with self.assertRaises(Exception) as context:
num2words(10 ** 36, to='year', lang='ar')
self.assertTrue('Too large' in str(context.exception))

34
tests/test_base.py Normal file
View File

@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from decimal import Decimal
from unittest import TestCase
from num2words.base import Num2Word_Base
class Num2WordBaseTest(TestCase):
@classmethod
def setUpClass(cls):
super(Num2WordBaseTest, cls).setUpClass()
cls.base = Num2Word_Base()
def test_to_currency_not_implemented(self):
with self.assertRaises(NotImplementedError):
self.base.to_currency(Decimal('1.00'), currency='EUR')

111
tests/test_cli.py Normal file
View File

@ -0,0 +1,111 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
import os
import unittest
import delegator
import num2words
class CliCaller(object):
def __init__(self):
self.cmd = os.path.realpath(os.path.join(os.path.dirname(__file__),
"..", "bin", "num2words"))
self.cmd_list = ["python", self.cmd]
def run_cmd(self, *args):
cmd_list = self.cmd_list + [str(arg) for arg in args]
cmd = " ".join(cmd_list)
return delegator.run(cmd)
class CliTestCase(unittest.TestCase):
"""Test the command line app"""
def setUp(self):
self.cli = CliCaller()
def test_cli_help(self):
"""num2words without arguments should exit with status 1
and show docopt's default short usage message
"""
output = self.cli.run_cmd()
self.assertEqual(output.return_code, 1)
self.assertTrue(output.err.startswith('Usage:'))
def test_cli_list_langs(self):
"""You should be able to list all availabe languages
"""
output = self.cli.run_cmd('--list-languages')
self.assertEqual(
sorted(list(num2words.CONVERTER_CLASSES.keys())),
output.out.strip().split(os.linesep)
)
output = self.cli.run_cmd('-L')
self.assertEqual(
sorted(list(num2words.CONVERTER_CLASSES.keys())),
output.out.strip().split(os.linesep)
)
def test_cli_list_converters(self):
"""You should be able to list all available converters
"""
output = self.cli.run_cmd('--list-converters')
self.assertEqual(
sorted(list(num2words.CONVERTES_TYPES)),
output.out.strip().split(os.linesep)
)
output = self.cli.run_cmd('-C')
self.assertEqual(
sorted(list(num2words.CONVERTES_TYPES)),
output.out.strip().split(os.linesep)
)
def test_cli_default_lang(self):
"""Default to english
"""
output = self.cli.run_cmd(150)
self.assertEqual(output.return_code, 0)
self.assertEqual(
output.out.strip(),
"one hundred and fifty point zero"
)
def test_cli_with_lang(self):
"""You should be able to specify a language
"""
output = self.cli.run_cmd(150, '--lang', 'es')
self.assertEqual(output.return_code, 0)
self.assertEqual(
output.out.strip(),
"ciento cincuenta punto cero"
)
def test_cli_with_lang_to(self):
"""You should be able to specify a language
"""
output = self.cli.run_cmd(150.55, '--lang', 'es', '--to', 'currency')
self.assertEqual(output.return_code, 0)
self.assertEqual(
output.out.strip(),
"ciento cincuenta euros con cincuenta y cinco centimos"
)

63
tests/test_currency.py Normal file
View File

@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from decimal import Decimal
from unittest import TestCase
from num2words.currency import parse_currency_parts
class CurrencyTestCase(TestCase):
def test_parse_currency_parts(self):
# integer with cents
self.assertEqual(parse_currency_parts(101), (1, 1, False))
self.assertEqual(parse_currency_parts(-123), (1, 23, True))
# integer without cents
self.assertEqual(parse_currency_parts(101, is_int_with_cents=False),
(101, 0, False))
self.assertEqual(parse_currency_parts(-123, is_int_with_cents=False),
(123, 0, True))
# float
self.assertEqual(parse_currency_parts(1.01), (1, 1, False))
self.assertEqual(parse_currency_parts(-1.23), (1, 23, True))
self.assertEqual(parse_currency_parts(-1.2), (1, 20, True))
self.assertEqual(parse_currency_parts(0.004), (0, 0, False))
self.assertEqual(parse_currency_parts(0.005), (0, 1, False))
self.assertEqual(parse_currency_parts(0.006), (0, 1, False))
self.assertEqual(parse_currency_parts(0.0005), (0, 0, False))
self.assertEqual(parse_currency_parts(0.984), (0, 98, False))
self.assertEqual(parse_currency_parts(0.989), (0, 99, False))
self.assertEqual(parse_currency_parts(0.994), (0, 99, False))
self.assertEqual(parse_currency_parts(0.999), (1, 0, False))
# self.assertEqual(parse_currency_parts(0.985), (0, 99, False))
# self.assertEqual(parse_currency_parts(0.995), (1, 0, False))
# decimal
self.assertEqual(parse_currency_parts(Decimal("1.01")), (1, 1, False))
self.assertEqual(parse_currency_parts(Decimal("-1.23")), (1, 23, True))
self.assertEqual(parse_currency_parts(Decimal("-1.233")),
(1, 23, True))
self.assertEqual(parse_currency_parts(Decimal("-1.989")),
(1, 99, True))
# string
self.assertEqual(parse_currency_parts("1.01"), (1, 1, False))
self.assertEqual(parse_currency_parts("-1.23"), (1, 23, True))
self.assertEqual(parse_currency_parts("-1.2"), (1, 20, True))
self.assertEqual(parse_currency_parts("1"), (1, 0, False))

106
tests/test_cz.py Normal file
View File

@ -0,0 +1,106 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
class Num2WordsCZTest(TestCase):
def test_cardinal(self):
self.assertEqual(num2words(100, lang='cz'), "sto")
self.assertEqual(num2words(101, lang='cz'), "sto jedna")
self.assertEqual(num2words(110, lang='cz'), "sto deset")
self.assertEqual(num2words(115, lang='cz'), "sto patnáct")
self.assertEqual(num2words(123, lang='cz'), "sto dvacet tři")
self.assertEqual(num2words(1000, lang='cz'), "tisíc")
self.assertEqual(num2words(1001, lang='cz'), "tisíc jedna")
self.assertEqual(num2words(2012, lang='cz'), "dva tisíce dvanáct")
self.assertEqual(
num2words(12519.85, lang='cz'),
"dvanáct tisíc pětset devatenáct celá osmdesát pět"
)
self.assertEqual(
num2words(123.50, lang='cz'),
"sto dvacet tři celá pět"
)
self.assertEqual(
num2words(1234567890, lang='cz'),
"miliarda dvěstě třicet čtyři miliony pětset šedesát "
"sedm tisíc osmset devadesát"
)
self.assertEqual(
num2words(215461407892039002157189883901676, lang='cz'),
"dvěstě patnáct quintillionů čtyřista šedesát jedna kvadriliard "
"čtyřista sedm kvadrilionů osmset devadesát dva triliardy třicet "
"devět trilionů dva biliardy sto padesát sedm bilionů sto "
"osmdesát devět miliard osmset osmdesát tři miliony "
"devětset jedna tisíc šestset sedmdesát šest"
)
self.assertEqual(
num2words(719094234693663034822824384220291, lang='cz'),
"sedmset devatenáct quintillionů devadesát "
"čtyři kvadriliardy dvěstě třicet čtyři "
"kvadriliony šestset devadesát tři triliardy "
"šestset šedesát tři triliony třicet čtyři biliardy osmset "
"dvacet dva biliony osmset dvacet čtyři "
"miliardy třista osmdesát čtyři miliony dvěstě dvacet "
"tisíc dvěstě devadesát jedna"
)
def test_to_ordinal(self):
# @TODO: implement to_ordinal
with self.assertRaises(NotImplementedError):
num2words(1, lang='cz', to='ordinal')
def test_currency(self):
self.assertEqual(
num2words(10.0, lang='cz', to='currency', currency='EUR'),
"deset euro, nula centů")
self.assertEqual(
num2words(1.0, lang='cz', to='currency', currency='CZK'),
"jedna koruna, nula haléřů")
self.assertEqual(
num2words(1234.56, lang='cz', to='currency', currency='EUR'),
"tisíc dvěstě třicet čtyři euro, padesát šest centů")
self.assertEqual(
num2words(1234.56, lang='cz', to='currency', currency='CZK'),
"tisíc dvěstě třicet čtyři koruny, padesát šest haléřů")
self.assertEqual(
num2words(101.11, lang='cz', to='currency', currency='EUR',
seperator=' a'),
"sto jedna euro a jedenáct centů")
self.assertEqual(
num2words(101.21, lang='cz', to='currency', currency='CZK',
seperator=' a'),
"sto jedna korun a dvacet jedna haléřů"
)
self.assertEqual(
num2words(-12519.85, lang='cz', to='currency', cents=False),
"mínus dvanáct tisíc pětset devatenáct euro, 85 centů"
)
self.assertEqual(
num2words(123.50, lang='cz', to='currency', currency='CZK',
seperator=' a'),
"sto dvacet tři koruny a padesát haléřů"
)
self.assertEqual(
num2words(19.50, lang='cz', to='currency', cents=False),
"devatenáct euro, 50 centů"
)

113
tests/test_de.py Normal file
View File

@ -0,0 +1,113 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
class Num2WordsDETest(TestCase):
def test_ordinal_less_than_twenty(self):
self.assertEqual(num2words(7, ordinal=True, lang='de'), "siebte")
self.assertEqual(num2words(8, ordinal=True, lang='de'), "achte")
self.assertEqual(num2words(12, ordinal=True, lang='de'), "zwölfte")
self.assertEqual(num2words(17, ordinal=True, lang='de'), "siebzehnte")
def test_ordinal_more_than_twenty(self):
self.assertEqual(
num2words(81, ordinal=True, lang='de'), "einundachtzigste"
)
def test_ordinal_at_crucial_number(self):
self.assertEqual(
num2words(100, ordinal=True, lang='de'), "hundertste"
)
self.assertEqual(
num2words(1000, ordinal=True, lang='de'), "tausendste"
)
self.assertEqual(
num2words(4000, ordinal=True, lang='de'), "viertausendste"
)
self.assertEqual(
num2words(2000000, ordinal=True, lang='de'), "zwei millionste"
)
self.assertEqual(
num2words(5000000000, ordinal=True, lang='de'),
"fünf milliardste"
)
def test_cardinal_at_some_numbers(self):
self.assertEqual(num2words(100, lang='de'), "einhundert")
self.assertEqual(num2words(2000000, lang='de'), "zwei millionen")
self.assertEqual(num2words(4000000000, lang='de'), "vier milliarden")
self.assertEqual(num2words(1000000000, lang='de'), "eine milliarde")
def test_cardinal_for_decimal_number(self):
self.assertEqual(
num2words(3.486, lang='de'), "drei Komma vier acht sechs"
)
def test_giant_cardinal_for_merge(self):
self.assertEqual(
num2words(4500072900000111, lang='de'),
"vier billiarden fünfhundert billionen " +
"zweiundsiebzig milliarden neunhundert millionen einhundertelf"
)
def test_ordinal_num(self):
self.assertEqual(num2words(7, to="ordinal_num", lang='de'), "7.")
self.assertEqual(num2words(81, to="ordinal_num", lang='de'), "81.")
def test_ordinal_for_negative_numbers(self):
self.assertRaises(TypeError, num2words, -12, ordinal=True, lang='de')
def test_ordinal_for_floating_numbers(self):
self.assertRaises(TypeError, num2words, 2.453, ordinal=True, lang='de')
def test_currency(self):
self.assertEqual(num2words(1, lang='de', to='currency'),
'ein Euro')
self.assertEqual(num2words(12, lang='de', to='currency'),
'zwölf Euro')
self.assertEqual(num2words(12.00, lang='de', to='currency'),
'zwölf Euro')
self.assertEqual(num2words(100.0, lang='de', to='currency'),
"einhundert Euro")
self.assertEqual(num2words(190, lang='de', to='currency'),
"einhundertneunzig Euro")
self.assertEqual(num2words(1.90, lang='de', to='currency'),
"ein Euro und neunzig Cent")
self.assertEqual(num2words(3.4, lang='de', to='currency'),
"drei Euro und vierzig Cent")
self.assertEqual(num2words(20.18, lang='de', to='currency'),
"zwanzig Euro und achtzehn Cent")
self.assertEqual(num2words(3.04, lang='de', to='currency'),
"drei Euro und vier Cent")
def test_old_currency(self):
self.assertEqual(num2words(12.00, to='currency', lang='de', old=True),
'zwölf Mark')
def test_year(self):
self.assertEqual(num2words(2002, to='year', lang='de'),
'zweitausendzwei')
def test_year_before_2000(self):
self.assertEqual(num2words(1780, to='year', lang='de'),
'siebzehnhundertachtzig')

172
tests/test_en.py Normal file
View File

@ -0,0 +1,172 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from unittest import TestCase
from num2words import num2words
class Num2WordsENTest(TestCase):
def test_and_join_199(self):
# ref https://github.com/savoirfairelinux/num2words/issues/8
self.assertEqual(num2words(199), "one hundred and ninety-nine")
def test_ordinal(self):
self.assertEqual(
num2words(1, lang='en', to='ordinal'),
'first'
)
self.assertEqual(
num2words(22, lang='en', to='ordinal'),
'twenty-second'
)
self.assertEqual(
num2words(12, lang='en', to='ordinal'),
'twelfth'
)
self.assertEqual(
num2words(130, lang='en', to='ordinal'),
'one hundred and thirtieth'
)
self.assertEqual(
num2words(1003, lang='en', to='ordinal'),
'one thousand and third'
)
def test_ordinal_num(self):
self.assertEqual(num2words(10, lang='en', to='ordinal_num'), '10th')
self.assertEqual(num2words(21, lang='en', to='ordinal_num'), '21st')
self.assertEqual(num2words(102, lang='en', to='ordinal_num'), '102nd')
self.assertEqual(num2words(73, lang='en', to='ordinal_num'), '73rd')
def test_cardinal_for_float_number(self):
# issue 24
self.assertEqual(num2words(12.5), "twelve point five")
self.assertEqual(num2words(12.51), "twelve point five one")
self.assertEqual(num2words(12.53), "twelve point five three")
self.assertEqual(num2words(12.59), "twelve point five nine")
def test_overflow(self):
with self.assertRaises(OverflowError):
num2words("1000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000")
def test_to_currency(self):
self.assertEqual(
num2words('38.4', lang='en', to='currency', seperator=' and',
cents=False, currency='USD'),
"thirty-eight dollars and 40 cents"
)
self.assertEqual(
num2words('0', lang='en', to='currency', seperator=' and',
cents=False, currency='USD'),
"zero dollars and 00 cents"
)
self.assertEqual(
num2words('1.01', lang='en', to='currency', seperator=' and',
cents=True, currency='USD'),
"one dollar and one cent"
)
self.assertEqual(
num2words('4778.00', lang='en', to='currency', seperator=' and',
cents=True, currency='USD', adjective=True),
'four thousand, seven hundred and seventy-eight US dollars'
' and zero cents')
self.assertEqual(
num2words('4778.00', lang='en', to='currency', seperator=' and',
cents=True, currency='USD'),
'four thousand, seven hundred and seventy-eight dollars and'
' zero cents')
self.assertEqual(
num2words('1.1', lang='en', to='currency', seperator=' and',
cents=True, currency='MXN'),
"one peso and ten cents"
)
self.assertEqual(
num2words('158.3', lang='en', to='currency', seperator=' and',
cents=True, currency='MXN'),
"one hundred and fifty-eight pesos and thirty cents"
)
self.assertEqual(
num2words('2000.00', lang='en', to='currency', seperator=' and',
cents=True, currency='MXN'),
"two thousand pesos and zero cents"
)
self.assertEqual(
num2words('4.01', lang='en', to='currency', seperator=' and',
cents=True, currency='MXN'),
"four pesos and one cent"
)
def test_to_year(self):
# issue 141
# "e2 e2"
self.assertEqual(num2words(1990, lang='en', to='year'),
'nineteen ninety')
self.assertEqual(num2words(5555, lang='en', to='year'),
'fifty-five fifty-five')
self.assertEqual(num2words(2017, lang='en', to='year'),
'twenty seventeen')
self.assertEqual(num2words(1066, lang='en', to='year'),
'ten sixty-six')
self.assertEqual(num2words(1865, lang='en', to='year'),
'eighteen sixty-five')
# "e3 and e1"; "e2 oh-e1"; "e3"
self.assertEqual(num2words(3000, lang='en', to='year'),
'three thousand')
self.assertEqual(num2words(2001, lang='en', to='year'),
'two thousand and one')
self.assertEqual(num2words(1901, lang='en', to='year'),
'nineteen oh-one')
self.assertEqual(num2words(2000, lang='en', to='year'),
'two thousand')
self.assertEqual(num2words(905, lang='en', to='year'),
'nine oh-five')
# "e2 hundred"; "e3"
self.assertEqual(num2words(6600, lang='en', to='year'),
'sixty-six hundred')
self.assertEqual(num2words(1900, lang='en', to='year'),
'nineteen hundred')
self.assertEqual(num2words(600, lang='en', to='year'),
'six hundred')
self.assertEqual(num2words(50, lang='en', to='year'),
'fifty')
self.assertEqual(num2words(0, lang='en', to='year'),
'zero')
# suffixes
self.assertEqual(num2words(-44, lang='en', to='year'),
'forty-four BC')
self.assertEqual(num2words(-44, lang='en', to='year', suffix='BCE'),
'forty-four BCE')
self.assertEqual(num2words(1, lang='en', to='year', suffix='AD'),
'one AD')
self.assertEqual(num2words(66, lang='en', to='year',
suffix='m.y.a.'),
'sixty-six m.y.a.')
self.assertEqual(num2words(-66000000, lang='en', to='year'),
'sixty-six million BC')

27
tests/test_en_in.py Normal file
View File

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from unittest import TestCase
from num2words import num2words
class Num2WordsENINTest(TestCase):
def test_cardinal(self):
self.assertEqual(num2words(1e5, lang="en_IN"), "one lakh")
self.assertEqual(num2words(1e6, lang="en_IN"), "ten lakh")
self.assertEqual(num2words(1e7, lang="en_IN"), "one crore")

205
tests/test_es.py Normal file
View File

@ -0,0 +1,205 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
TEST_CASES_CARDINAL = (
(1, 'uno'),
(2, 'dos'),
(3, 'tres'),
(5.5, 'cinco punto cinco'),
(11, 'once'),
(12, 'doce'),
(16, 'dieciseis'),
(17.42, 'diecisiete punto cuatro dos'),
(19, 'diecinueve'),
(20, 'veinte'),
(21, 'veintiuno'),
(26, 'veintiséis'),
(27.312, 'veintisiete punto tres uno dos'),
(28, 'veintiocho'),
(30, 'treinta'),
(31, 'treinta y uno'),
(40, 'cuarenta'),
(44, 'cuarenta y cuatro'),
(50, 'cincuenta'),
(53.486, 'cincuenta y tres punto cuatro ocho seis'),
(55, 'cincuenta y cinco'),
(60, 'sesenta'),
(67, 'sesenta y siete'),
(70, 'setenta'),
(79, 'setenta y nueve'),
(89, 'ochenta y nueve'),
(95, 'noventa y cinco'),
(100, 'cien'),
(101, 'ciento uno'),
(199, 'ciento noventa y nueve'),
(203, 'doscientos tres'),
(287, 'doscientos ochenta y siete'),
(300.42, 'trescientos punto cuatro dos'),
(356, 'trescientos cincuenta y seis'),
(400, 'cuatrocientos'),
(434, 'cuatrocientos treinta y cuatro'),
(578, 'quinientos setenta y ocho'),
(689, 'seiscientos ochenta y nueve'),
(729, 'setecientos veintinueve'),
(894, 'ochocientos noventa y cuatro'),
(999, 'novecientos noventa y nueve'),
(1000, 'mil'),
(1001, 'mil uno'),
(1097, 'mil noventa y siete'),
(1104, 'mil ciento cuatro'),
(1243, 'mil doscientos cuarenta y tres'),
(2385, 'dos mil trescientos ochenta y cinco'),
(3766, 'tres mil setecientos sesenta y seis'),
(4196, 'cuatro mil ciento noventa y seis'),
(4196.42, 'cuatro mil ciento noventa y seis punto cuatro dos'),
(5846, 'cinco mil ochocientos cuarenta y seis'),
(6459, 'seis mil cuatrocientos cincuenta y nueve'),
(7232, 'siete mil doscientos treinta y dos'),
(8569, 'ocho mil quinientos sesenta y nueve'),
(9539, 'nueve mil quinientos treinta y nueve'),
(1000000, 'un millón'),
(1000001, 'un millón uno'),
(4000000, 'cuatro millones'),
(10000000000000, 'diez billones'),
(100000000000000, 'cien billones'),
(1000000000000000000, 'un trillón'),
(1000000000000000000000, 'mil trillones'),
(10000000000000000000000000, 'diez cuatrillones')
)
TEST_CASES_ORDINAL = (
(1, 'primero'),
(8, 'octavo'),
(12, 'décimosegundo'),
(14, 'décimo cuarto'),
(28, 'vigésimo octavo'),
(100, 'centésimo'),
(1000, 'milésimo'),
(1000000, 'millonésimo'),
(1000000000000000, 'cuadrillonésimo'),
(1000000000000000000, 'un trillón') # over 1e18 is not supported
)
TEST_CASES_ORDINAL_NUM = (
(1, ''),
(8, ''),
(12, '12º'),
(14, '14º'),
(28, '28º'),
(100, '100º'),
(1000, '1000º'),
(1000000, '1000000º')
)
TEST_CASES_TO_CURRENCY = (
(1.00, 'un euro con cero centimos'),
(2.00, 'dos euros con cero centimos'),
(8.00, 'ocho euros con cero centimos'),
(12.00, 'doce euros con cero centimos'),
(21.00, 'veintiun euros con cero centimos'),
(81.25, 'ochenta y un euros con veinticinco centimos'),
(350.90, 'trescientos cincuenta euros con noventa centimos'),
(100.00, 'cien euros con cero centimos'),
)
TEST_CASES_TO_CURRENCY_ESP = (
(1.00, 'un peseta con cero centimos'),
(2.00, 'dos pesetas con cero centimos'),
(8.00, 'ocho pesetas con cero centimos'),
(12.00, 'doce pesetas con cero centimos'),
(21.00, 'veintiun pesetas con cero centimos'),
(81.25, 'ochenta y un pesetas con veinticinco centimos'),
(350.90, 'trescientos cincuenta pesetas con noventa centimos'),
(100.00, 'cien pesetas con cero centimos'),
)
TEST_CASES_TO_CURRENCY_USD = (
(1.00, 'un dolar con cero centavos'),
(2.00, 'dos dolares con cero centavos'),
(8.00, 'ocho dolares con cero centavos'),
(12.00, 'doce dolares con cero centavos'),
(21.00, 'veintiun dolares con cero centavos'),
(81.25, 'ochenta y un dolares con veinticinco centavos'),
(350.90, 'trescientos cincuenta dolares con noventa centavos'),
(100.00, 'cien dolares con cero centavos'),
)
TEST_CASES_TO_CURRENCY_PEN = (
(1.00, 'un sol con cero centimos'),
(2.00, 'dos soles con cero centimos'),
(8.00, 'ocho soles con cero centimos'),
(12.00, 'doce soles con cero centimos'),
(21.00, 'veintiun soles con cero centimos'),
(81.25, 'ochenta y un soles con veinticinco centimos'),
(350.90, 'trescientos cincuenta soles con noventa centimos'),
(100.00, 'cien soles con cero centimos'),
)
class Num2WordsESTest(TestCase):
def test_number(self):
for test in TEST_CASES_CARDINAL:
self.assertEqual(num2words(test[0], lang='es'), test[1])
def test_ordinal(self):
for test in TEST_CASES_ORDINAL:
self.assertEqual(
num2words(test[0], lang='es', ordinal=True),
test[1]
)
def test_ordinal_num(self):
for test in TEST_CASES_ORDINAL_NUM:
self.assertEqual(
num2words(test[0], lang='es', to='ordinal_num'),
test[1]
)
def test_currency(self):
for test in TEST_CASES_TO_CURRENCY:
self.assertEqual(
num2words(test[0], lang='es', to='currency'),
test[1]
)
def test_currency_esp(self):
for test in TEST_CASES_TO_CURRENCY_ESP:
self.assertEqual(
num2words(test[0], lang='es', to='currency', currency='ESP'),
test[1]
)
def test_currency_usd(self):
for test in TEST_CASES_TO_CURRENCY_USD:
self.assertEqual(
num2words(test[0], lang='es', to='currency', currency='USD'),
test[1]
)
def test_currency_pen(self):
for test in TEST_CASES_TO_CURRENCY_PEN:
self.assertEqual(
num2words(test[0], lang='es', to='currency', currency='PEN'),
test[1]
)

60
tests/test_es_co.py Normal file
View File

@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from num2words import num2words
from . import test_es
TEST_CASES_TO_CURRENCY = (
(1, 'un peso'),
(2, 'dos pesos'),
(8, 'ocho pesos'),
(12, 'doce pesos'),
(21, 'veintiun pesos'),
(81.25, 'ochenta y un pesos y veinticinco centavos'),
(100, 'cien pesos'),
)
class Num2WordsESCOTest(test_es.Num2WordsESTest):
def test_number(self):
for test in test_es.TEST_CASES_CARDINAL:
self.assertEqual(num2words(test[0], lang='es_CO'), test[1])
def test_ordinal(self):
for test in test_es.TEST_CASES_ORDINAL:
self.assertEqual(
num2words(test[0], lang='es_CO', ordinal=True),
test[1]
)
def test_ordinal_num(self):
for test in test_es.TEST_CASES_ORDINAL_NUM:
self.assertEqual(
num2words(test[0], lang='es', to='ordinal_num'),
test[1]
)
def test_currency(self):
for test in TEST_CASES_TO_CURRENCY:
self.assertEqual(
num2words(test[0], lang='es_CO', to='currency'),
test[1]
)

59
tests/test_es_ve.py Normal file
View File

@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from num2words import num2words
from . import test_es
TEST_CASES_TO_CURRENCY = (
(1, 'un bolívar'),
(2, 'dos bolívares'),
(8, 'ocho bolívares'),
(12, 'doce bolívares'),
(21, 'veintiun bolívares'),
(81.25, 'ochenta y un bolívares y veinticinco centavos'),
(100, 'cien bolívares'),
)
class Num2WordsESVETest(test_es.Num2WordsESTest):
def test_number(self):
for test in test_es.TEST_CASES_CARDINAL:
self.assertEqual(num2words(test[0], lang='es_VE'), test[1])
def test_ordinal(self):
for test in test_es.TEST_CASES_ORDINAL:
self.assertEqual(
num2words(test[0], lang='es_VE', ordinal=True),
test[1]
)
def test_ordinal_num(self):
for test in test_es.TEST_CASES_ORDINAL_NUM:
self.assertEqual(
num2words(test[0], lang='es', to='ordinal_num'),
test[1]
)
def test_currency(self):
for test in TEST_CASES_TO_CURRENCY:
self.assertEqual(
num2words(test[0], lang='es_VE', to='currency', old=True),
test[1]
)

2762
tests/test_fi.py Normal file

File diff suppressed because it is too large Load Diff

187
tests/test_fr.py Normal file
View File

@ -0,0 +1,187 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
TEST_CASES_CARDINAL = (
(1, 'un'),
(2, 'deux'),
(3, 'trois'),
(5.5, 'cinq virgule cinq'),
(11, 'onze'),
(12, 'douze'),
(16, 'seize'),
(17.42, 'dix-sept virgule quatre deux'),
(19, 'dix-neuf'),
(20, 'vingt'),
(21, 'vingt et un'),
(26, 'vingt-six'),
(27.312, 'vingt-sept virgule trois un deux'),
(28, 'vingt-huit'),
(30, 'trente'),
(31, 'trente et un'),
(40, 'quarante'),
(44, 'quarante-quatre'),
(50, 'cinquante'),
(53.486, 'cinquante-trois virgule quatre huit six'),
(55, 'cinquante-cinq'),
(60, 'soixante'),
(67, 'soixante-sept'),
(70, 'soixante-dix'),
(79, 'soixante-dix-neuf'),
(89, 'quatre-vingt-neuf'),
(95, 'quatre-vingt-quinze'),
(100, 'cent'),
(101, 'cent un'),
(199, 'cent quatre-vingt-dix-neuf'),
(203, 'deux cent trois'),
(287, 'deux cent quatre-vingt-sept'),
(300.42, 'trois cents virgule quatre deux'),
(356, 'trois cent cinquante-six'),
(400, 'quatre cents'),
(434, 'quatre cent trente-quatre'),
(578, 'cinq cent soixante-dix-huit'),
(689, 'six cent quatre-vingt-neuf'),
(729, 'sept cent vingt-neuf'),
(894, 'huit cent quatre-vingt-quatorze'),
(999, 'neuf cent quatre-vingt-dix-neuf'),
(1000, 'mille'),
(1001, 'mille un'),
(1097, 'mille quatre-vingt-dix-sept'),
(1104, 'mille cent quatre'),
(1243, 'mille deux cent quarante-trois'),
(2385, 'deux mille trois cent quatre-vingt-cinq'),
(3766, 'trois mille sept cent soixante-six'),
(4196, 'quatre mille cent quatre-vingt-seize'),
(4196.42, 'quatre mille cent quatre-vingt-seize virgule quatre deux'),
(5846, 'cinq mille huit cent quarante-six'),
(6459, 'six mille quatre cent cinquante-neuf'),
(7232, 'sept mille deux cent trente-deux'),
(8569, 'huit mille cinq cent soixante-neuf'),
(9539, 'neuf mille cinq cent trente-neuf'),
(1000000, 'un million'),
(1000001, 'un million un'),
(4000000, 'quatre millions'),
(4000004, 'quatre millions quatre'),
(4300000, 'quatre millions trois cent mille'),
(80000000, 'quatre-vingts millions'),
(300000000, 'trois cents millions'),
(10000000000000, 'dix billions'),
(10000000000010, 'dix billions dix'),
(100000000000000, 'cent billions'),
(1000000000000000000, 'un trillion'),
(1000000000000000000000, 'un trilliard'),
(10000000000000000000000000, 'dix quadrillions')
)
TEST_CASES_ORDINAL = (
(1, 'premier'),
(8, 'huitième'),
(12, 'douzième'),
(14, 'quatorzième'),
(28, 'vingt-huitième'),
(100, 'centième'),
(1000, 'millième'),
(1000000, 'un millionième'),
(1000000000000000, 'un billiardième'),
(1000000000000000000, 'un trillionième') # over 1e18 is not supported
)
TEST_CASES_ORDINAL_NUM = (
(1, '1er'),
(8, '8me'),
(12, '12me'),
(14, '14me'),
(28, '28me'),
(100, '100me'),
(1000, '1000me'),
(1000000, '1000000me')
)
TEST_CASES_TO_CURRENCY = (
(1, 'un euro'),
(2, 'deux euros'),
(8, 'huit euros'),
(12, 'douze euros'),
(21, 'vingt et un euros'),
(81.25, 'quatre-vingt-un euros et vingt-cinq centimes'),
(81.2, 'quatre-vingt-un euros et vingt centimes'),
(100, 'cent euros'),
)
TEST_CASES_TO_CURRENCY_OLD = (
(1, 'un franc'),
(2, 'deux francs'),
(8, 'huit francs'),
(12, 'douze francs'),
(21, 'vingt et un francs'),
(81.25, 'quatre-vingt-un francs et vingt-cinq centimes'),
(81.2, 'quatre-vingt-un francs et vingt centimes'),
(100, 'cent francs'),
)
class Num2WordsENTest(TestCase):
def test_ordinal_special_joins(self):
# ref https://github.com/savoirfairelinux/num2words/issues/18
self.assertEqual(
num2words(5, ordinal=True, lang='fr'), "cinquième"
)
self.assertEqual(
num2words(35, ordinal=True, lang='fr'), "trente-cinquième"
)
self.assertEqual(
num2words(9, ordinal=True, lang='fr'), "neuvième"
)
self.assertEqual(
num2words(49, ordinal=True, lang='fr'), "quarante-neuvième"
)
def test_number(self):
for test in TEST_CASES_CARDINAL:
self.assertEqual(num2words(test[0], lang='fr'), test[1])
def test_ordinal(self):
for test in TEST_CASES_ORDINAL:
self.assertEqual(
num2words(test[0], lang='fr', ordinal=True),
test[1]
)
def test_ordinal_num(self):
for test in TEST_CASES_ORDINAL_NUM:
self.assertEqual(
num2words(test[0], lang='fr', to='ordinal_num'),
test[1]
)
def test_currency(self):
for test in TEST_CASES_TO_CURRENCY:
self.assertEqual(
num2words(test[0], lang='fr', to='currency'),
test[1]
)
def test_currency_old(self):
for test in TEST_CASES_TO_CURRENCY_OLD:
self.assertEqual(
num2words(test[0], lang='fr', to='currency', old=True),
test[1]
)

129
tests/test_fr_be.py Normal file
View File

@ -0,0 +1,129 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
TEST_CASES_CARDINAL = (
(70, 'septante'),
(79, 'septante-neuf'),
(89, 'quatre-vingt-neuf'),
(95, 'nonante-cinq'),
(729, 'sept cents vingt-neuf'),
(894, 'huit cents nonante-quatre'),
(999, 'neuf cents nonante-neuf'),
(7232, 'sept mille deux cents trente-deux'),
(8569, 'huit mille cinq cents soixante-neuf'),
(9539, 'neuf mille cinq cents trente-neuf'),
(1000000, 'un millions'),
(1000001, 'un millions un'),
(4000000, 'quatre millions'),
(10000000000000, 'dix billions'),
(100000000000000, 'cent billions'),
(1000000000000000000, 'un trillions'),
(1000000000000000000000, 'un trilliards'),
(10000000000000000000000000, 'dix quadrillions')
)
TEST_CASES_ORDINAL = (
(1, 'premier'),
(8, 'huitième'),
(12, 'douzième'),
(14, 'quatorzième'),
(28, 'vingt-huitième'),
(100, 'centième'),
(1000, 'millième'),
(1000000, 'un millionsième'),
(1000000000000000, 'un billiardsième'),
(1000000000000000000, 'un trillionsième') # over 1e18 is not supported
)
TEST_CASES_TO_CURRENCY = (
(1, 'un euro'),
(2, 'deux euros'),
(8, 'huit euros'),
(12, 'douze euros'),
(21, 'vingt et un euros'),
(81.25, 'quatre-vingt et un euros et vingt-cinq centimes'),
(100, 'cent euros'),
)
TEST_CASES_TO_CURRENCY_OLD = (
(1, 'un franc'),
(2, 'deux francs'),
(8, 'huit francs'),
(12, 'douze francs'),
(21, 'vingt et un francs'),
(81.25, 'quatre-vingt et un francs et vingt-cinq centimes'),
(100, 'cent francs'),
)
# Lang to execute current test
LANG = 'fr_BE'
class Num2WordsENTest(TestCase):
def test_ordinal_special_joins(self):
self.assertEqual(
num2words(5, ordinal=True, lang=LANG), "cinquième"
)
self.assertEqual(
num2words(6, ordinal=True, lang=LANG), "sixième"
)
self.assertEqual(
num2words(35, ordinal=True, lang=LANG), "trente-cinquième"
)
self.assertEqual(num2words(9, ordinal=True, lang=LANG), "neuvième")
self.assertEqual(
num2words(49, ordinal=True, lang=LANG), "quarante-neuvième"
)
self.assertEqual(num2words(71, lang=LANG), "septante et un")
self.assertEqual(num2words(81, lang=LANG), "quatre-vingt et un")
self.assertEqual(num2words(80, lang=LANG), "quatre-vingt")
self.assertEqual(
num2words(880, lang=LANG), "huit cents quatre-vingt")
self.assertEqual(
num2words(91, ordinal=True, lang=LANG), "nonante et unième"
)
self.assertEqual(num2words(53, lang=LANG), "cinquante-trois")
def test_number(self):
for test in TEST_CASES_CARDINAL:
self.assertEqual(num2words(test[0], lang=LANG), test[1])
def test_ordinal(self):
for test in TEST_CASES_ORDINAL:
self.assertEqual(
num2words(test[0], lang=LANG, ordinal=True),
test[1]
)
def test_currency(self):
for test in TEST_CASES_TO_CURRENCY:
self.assertEqual(
num2words(test[0], lang=LANG, to='currency'),
test[1]
)
def test_currency_old(self):
for test in TEST_CASES_TO_CURRENCY_OLD:
self.assertEqual(
num2words(test[0], lang=LANG, to='currency', old=True),
test[1]
)

126
tests/test_fr_ch.py Normal file
View File

@ -0,0 +1,126 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
TEST_CASES_CARDINAL = (
(70, 'septante'),
(79, 'septante-neuf'),
(89, 'huitante-neuf'),
(95, 'nonante-cinq'),
(729, 'sept cents vingt-neuf'),
(894, 'huit cents nonante-quatre'),
(999, 'neuf cents nonante-neuf'),
(7232, 'sept mille deux cents trente-deux'),
(8569, 'huit mille cinq cents soixante-neuf'),
(9539, 'neuf mille cinq cents trente-neuf'),
(1000000, 'un millions'),
(1000001, 'un millions un'),
(4000000, 'quatre millions'),
(10000000000000, 'dix billions'),
(100000000000000, 'cent billions'),
(1000000000000000000, 'un trillions'),
(1000000000000000000000, 'un trilliards'),
(10000000000000000000000000, 'dix quadrillions')
)
TEST_CASES_ORDINAL = (
(1, 'premier'),
(8, 'huitième'),
(12, 'douzième'),
(14, 'quatorzième'),
(28, 'vingt-huitième'),
(100, 'centième'),
(1000, 'millième'),
(1000000, 'un millionsième'),
(1000000000000000, 'un billiardsième'),
(1000000000000000000, 'un trillionsième') # over 1e18 is not supported
)
TEST_CASES_TO_CURRENCY = (
(1, 'un euro'),
(2, 'deux euros'),
(8, 'huit euros'),
(12, 'douze euros'),
(21, 'vingt et un euros'),
(81.25, 'huitante et un euros et vingt-cinq centimes'),
(100, 'cent euros'),
)
TEST_CASES_TO_CURRENCY_OLD = (
(1, 'un franc'),
(2, 'deux francs'),
(8, 'huit francs'),
(12, 'douze francs'),
(21, 'vingt et un francs'),
(81.25, 'huitante et un francs et vingt-cinq centimes'),
(100, 'cent francs'),
)
class Num2WordsENTest(TestCase):
def test_ordinal_special_joins(self):
self.assertEqual(
num2words(5, ordinal=True, lang='fr_CH'), "cinquième"
)
self.assertEqual(
num2words(6, ordinal=True, lang='fr_CH'), "sixième"
)
self.assertEqual(
num2words(35, ordinal=True, lang='fr_CH'), "trente-cinquième"
)
self.assertEqual(num2words(9, ordinal=True, lang='fr_CH'), "neuvième")
self.assertEqual(
num2words(49, ordinal=True, lang='fr_CH'), "quarante-neuvième"
)
self.assertEqual(num2words(71, lang='fr_CH'), "septante et un")
self.assertEqual(num2words(81, lang='fr_CH'), "huitante et un")
self.assertEqual(num2words(80, lang='fr_CH'), "huitante")
self.assertEqual(num2words(880, lang='fr_CH'), "huit cents huitante")
self.assertEqual(
num2words(91, ordinal=True, lang='fr_CH'), "nonante et unième"
)
self.assertEqual(num2words(53, lang='fr_CH'), "cinquante-trois")
def test_number(self):
for test in TEST_CASES_CARDINAL:
self.assertEqual(num2words(test[0], lang='fr_CH'), test[1])
def test_ordinal(self):
for test in TEST_CASES_ORDINAL:
self.assertEqual(
num2words(test[0], lang='fr_CH', ordinal=True),
test[1]
)
def test_currency(self):
for test in TEST_CASES_TO_CURRENCY:
self.assertEqual(
num2words(test[0], lang='fr_CH', to='currency'),
test[1]
)
def test_currency_old(self):
for test in TEST_CASES_TO_CURRENCY_OLD:
self.assertEqual(
num2words(test[0], lang='fr_CH', to='currency', old=True),
test[1]
)

65
tests/test_fr_dz.py Normal file
View File

@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
from . import test_fr
TEST_CASES_TO_CURRENCY = (
(1, 'un dinard'),
(2, 'deux dinards'),
(8, 'huit dinards'),
(12, 'douze dinards'),
(21, 'vingt et un dinards'),
(81.25, 'quatre-vingt-un dinards virgule vingt-cinq centimes'),
(100, 'cent dinards'),
)
class Num2WordsPLTest(TestCase):
def test_currency(self):
self.assertEqual(
num2words(1234.12, lang='fr_DZ', to='currency'),
"mille deux cent trente-quatre dinards virgule douze centimes"
)
self.assertEqual(
num2words(45689.89, lang='fr_DZ', to='currency'),
"quarante-cinq mille six cent quatre-vingt-neuf dinards virgule "
"quatre-vingt-neuf centimes"
)
def test_number(self):
for test in test_fr.TEST_CASES_CARDINAL:
self.assertEqual(num2words(test[0], lang='fr_DZ'), test[1])
def test_ordinal(self):
for test in test_fr.TEST_CASES_ORDINAL:
self.assertEqual(
num2words(test[0], lang='fr_DZ', ordinal=True),
test[1]
)
def test_ordinal_num(self):
for test in test_fr.TEST_CASES_ORDINAL_NUM:
self.assertEqual(
num2words(test[0], lang='fr_DZ', to='ordinal_num'),
test[1]
)

62
tests/test_id.py Normal file
View File

@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from unittest import TestCase
from num2words import num2words
class Num2WordsIDTest(TestCase):
def test_cardinal_for_natural_number(self):
self.assertEqual(num2words(10, lang='id'), "sepuluh")
self.assertEqual(num2words(11, lang='id'), "sebelas")
self.assertEqual(num2words(108, lang='id'), "seratus delapan")
self.assertEqual(num2words(1075, lang='id'), "seribu tujuh puluh lima")
self.assertEqual(
num2words(1087231, lang='id'),
"satu juta delapan puluh tujuh ribu dua ratus tiga puluh satu"
)
self.assertEqual(
num2words(1000000408, lang='id'),
"satu miliar empat ratus delapan"
)
def test_cardinal_for_decimal_number(self):
self.assertEqual(
num2words(12.234, lang='id'), "dua belas koma dua tiga empat"
)
self.assertEqual(
num2words(9.076, lang='id'), "sembilan koma nol tujuh enam"
)
def test_cardinal_for_negative_number(self):
self.assertEqual(
num2words(-923, lang='id'), "min sembilan ratus dua puluh tiga"
)
self.assertEqual(
num2words(-0.234, lang='id'), "min nol koma dua tiga empat"
)
def test_ordinal_for_natural_number(self):
self.assertEqual(num2words(1, ordinal=True, lang='id'), "pertama")
self.assertEqual(num2words(10, ordinal=True, lang='id'), "kesepuluh")
def test_ordinal_for_negative_number(self):
self.assertRaises(TypeError, num2words, -12, ordinal=True, lang='id')
def test_ordinal_for_floating_number(self):
self.assertRaises(TypeError, num2words, 3.243, ordinal=True, lang='id')

235
tests/test_it.py Normal file
View File

@ -0,0 +1,235 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
class Num2WordsITTest(TestCase):
maxDiff = None
def test_negative(self):
number = 648972145
pos_crd = num2words(+number, lang="it")
neg_crd = num2words(-number, lang="it")
pos_ord = num2words(+number, lang="it", ordinal=True)
neg_ord = num2words(-number, lang="it", ordinal=True)
self.assertEqual("meno " + pos_crd, neg_crd)
self.assertEqual("meno " + pos_ord, neg_ord)
def test_float_to_cardinal(self):
self.assertEqual(
num2words(3.1415, lang="it"), "tre virgola uno quattro uno cinque"
)
self.assertEqual(
num2words(-5.15, lang="it"), "meno cinque virgola uno cinque"
)
self.assertEqual(
num2words(-0.15, lang="it"), "meno zero virgola uno cinque"
)
def test_float_to_ordinal(self):
self.assertEqual(
num2words(3.1415, lang="it", ordinal=True),
"terzo virgola uno quattro uno cinque"
)
self.assertEqual(
num2words(-5.15, lang="it", ordinal=True),
"meno quinto virgola uno cinque"
)
self.assertEqual(
num2words(-0.15, lang="it", ordinal=True),
"meno zero virgola uno cinque"
)
def test_0(self):
self.assertEqual(num2words(0, lang="it"), "zero")
self.assertEqual(num2words(0, lang="it", ordinal=True), "zero")
def test_1_to_10(self):
self.assertEqual(num2words(1, lang="it"), "uno")
self.assertEqual(num2words(2, lang="it"), "due")
self.assertEqual(num2words(7, lang="it"), "sette")
self.assertEqual(num2words(10, lang="it"), "dieci")
def test_11_to_19(self):
self.assertEqual(num2words(11, lang="it"), "undici")
self.assertEqual(num2words(13, lang="it"), "tredici")
self.assertEqual(num2words(15, lang="it"), "quindici")
self.assertEqual(num2words(16, lang="it"), "sedici")
self.assertEqual(num2words(19, lang="it"), "diciannove")
def test_20_to_99(self):
self.assertEqual(num2words(20, lang="it"), "venti")
self.assertEqual(num2words(23, lang="it"), "ventitré")
self.assertEqual(num2words(28, lang="it"), "ventotto")
self.assertEqual(num2words(31, lang="it"), "trentuno")
self.assertEqual(num2words(40, lang="it"), "quaranta")
self.assertEqual(num2words(66, lang="it"), "sessantasei")
self.assertEqual(num2words(92, lang="it"), "novantadue")
def test_100_to_999(self):
self.assertEqual(num2words(100, lang="it"), "cento")
self.assertEqual(num2words(111, lang="it"), "centoundici")
self.assertEqual(num2words(150, lang="it"), "centocinquanta")
self.assertEqual(num2words(196, lang="it"), "centonovantasei")
self.assertEqual(num2words(200, lang="it"), "duecento")
self.assertEqual(num2words(210, lang="it"), "duecentodieci")
self.assertEqual(num2words(701, lang="it"), "settecentouno")
def test_1000_to_9999(self):
self.assertEqual(num2words(1000, lang="it"), "mille")
self.assertEqual(num2words(1001, lang="it"), "milleuno")
self.assertEqual(num2words(1500, lang="it"), "millecinquecento")
self.assertEqual(
num2words(7378, lang="it"), "settemilatrecentosettantotto"
)
self.assertEqual(num2words(2000, lang="it"), "duemila")
self.assertEqual(num2words(2100, lang="it"), "duemilacento")
self.assertEqual(
num2words(6870, lang="it"), "seimilaottocentosettanta"
)
self.assertEqual(num2words(10000, lang="it"), "diecimila")
self.assertEqual(
num2words(98765, lang="it"),
"novantottomilasettecentosessantacinque"
)
self.assertEqual(num2words(100000, lang="it"), "centomila")
self.assertEqual(
num2words(523456, lang="it"),
"cinquecentoventitremilaquattrocentocinquantasei"
)
def test_big(self):
self.assertEqual(num2words(1000000, lang="it"), "un milione")
self.assertEqual(num2words(1000007, lang="it"), "un milione e sette")
self.assertEqual(
num2words(1200000, lang="it"), "un milione e duecentomila"
)
self.assertEqual(num2words(3000000, lang="it"), "tre milioni")
self.assertEqual(num2words(3000005, lang="it"), "tre milioni e cinque")
self.assertEqual(
num2words(3800000, lang="it"), "tre milioni e ottocentomila"
)
self.assertEqual(num2words(1000000000, lang="it"), "un miliardo")
self.assertEqual(
num2words(1000000017, lang="it"), "un miliardo e diciassette"
)
self.assertEqual(num2words(2000000000, lang="it"), "due miliardi")
self.assertEqual(
num2words(2000001000, lang="it"), "due miliardi e mille"
)
self.assertEqual(
num2words(1234567890, lang="it"),
"un miliardo, duecentotrentaquattro milioni e "
"cinquecentosessantasettemilaottocentonovanta"
)
self.assertEqual(num2words(1000000000000, lang="it"), "un bilione")
self.assertEqual(
num2words(123456789012345678901234567890, lang="it"),
"centoventitré quadriliardi, quattrocentocinquantasei "
"quadrilioni, settecentottantanove triliardi, dodici trilioni, "
"trecentoquarantacinque biliardi, seicentosettantotto bilioni, "
"novecentouno miliardi, duecentotrentaquattro milioni e "
"cinquecentosessantasettemilaottocentonovanta"
)
def test_nth_1_to_99(self):
self.assertEqual(num2words(1, lang="it", ordinal=True), "primo")
self.assertEqual(num2words(8, lang="it", ordinal=True), "ottavo")
self.assertEqual(
num2words(23, lang="it", ordinal=True), "ventitreesimo"
)
self.assertEqual(
num2words(47, lang="it", ordinal=True), "quarantasettesimo"
)
self.assertEqual(
num2words(99, lang="it", ordinal=True), "novantanovesimo"
)
def test_nth_100_to_999(self):
self.assertEqual(num2words(100, lang="it", ordinal=True), "centesimo")
self.assertEqual(
num2words(112, lang="it", ordinal=True), "centododicesimo"
)
self.assertEqual(
num2words(120, lang="it", ordinal=True), "centoventesimo"
)
self.assertEqual(
num2words(316, lang="it", ordinal=True), "trecentosedicesimo"
)
self.assertEqual(
num2words(700, lang="it", ordinal=True), "settecentesimo"
)
self.assertEqual(
num2words(803, lang="it", ordinal=True), "ottocentotreesimo"
)
self.assertEqual(
num2words(923, lang="it", ordinal=True), "novecentoventitreesimo"
)
def test_nth_1000_to_999999(self):
self.assertEqual(num2words(1000, lang="it", ordinal=True), "millesimo")
self.assertEqual(
num2words(1001, lang="it", ordinal=True), "milleunesimo"
)
self.assertEqual(
num2words(1003, lang="it", ordinal=True), "milletreesimo"
)
self.assertEqual(
num2words(1200, lang="it", ordinal=True), "milleduecentesimo"
)
self.assertEqual(
num2words(8640, lang="it", ordinal=True),
"ottomilaseicentoquarantesimo"
)
self.assertEqual(
num2words(14000, lang="it", ordinal=True), "quattordicimillesimo"
)
self.assertEqual(
num2words(123456, lang="it", ordinal=True),
"centoventitremilaquattrocentocinquantaseiesimo"
)
self.assertEqual(
num2words(987654, lang="it", ordinal=True),
"novecentottantasettemilaseicentocinquantaquattresimo"
)
def test_nth_big(self):
self.assertEqual(
num2words(1000000001, lang="it", ordinal=True),
"un miliardo e unesimo"
)
self.assertEqual(
num2words(123456789012345678901234567890, lang="it", ordinal=True),
"centoventitré quadriliardi, quattrocentocinquantasei "
"quadrilioni, settecentottantanove triliardi, dodici trilioni, "
"trecentoquarantacinque biliardi, seicentosettantotto bilioni, "
"novecentouno miliardi, duecentotrentaquattro milioni e "
"cinquecentosessantasettemilaottocentonovantesimo"
)
def test_with_decimals(self):
self.assertAlmostEqual(
num2words(1.0, lang="it"), "uno virgola zero"
)
self.assertAlmostEqual(
num2words(1.1, lang="it"), "uno virgola uno"
)

185
tests/test_ja.py Normal file
View File

@ -0,0 +1,185 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import division, print_function, unicode_literals
from unittest import TestCase
from num2words import num2words
def n2j(*args, **kwargs):
return num2words(*args, lang='ja', **kwargs)
class Num2WordsJATest(TestCase):
def test_low(self):
self.assertEqual(n2j(0), "")
self.assertEqual(n2j(0, prefer=[""]), "")
self.assertEqual(n2j(0, reading=True), "ゼロ")
self.assertEqual(n2j(0, reading=True, prefer=["れい"]), "れい")
self.assertEqual(n2j(1), "")
self.assertEqual(n2j(1, reading=True), "いち")
self.assertEqual(n2j(2), "")
self.assertEqual(n2j(2, reading=True), "")
self.assertEqual(n2j(3), "")
self.assertEqual(n2j(3, reading=True), "さん")
self.assertEqual(n2j(4), "")
self.assertEqual(n2j(4, reading=True), "よん")
self.assertEqual(n2j(4, reading=True, prefer=[""]), "")
self.assertEqual(n2j(5), "")
self.assertEqual(n2j(5, reading=True), "")
self.assertEqual(n2j(6), "")
self.assertEqual(n2j(6, reading=True), "ろく")
self.assertEqual(n2j(7), "")
self.assertEqual(n2j(7, reading=True), "なな")
self.assertEqual(n2j(7, reading=True, prefer=["しち"]), "しち")
self.assertEqual(n2j(8), "")
self.assertEqual(n2j(8, reading=True), "はち")
self.assertEqual(n2j(9), "")
self.assertEqual(n2j(9, reading=True), "きゅう")
self.assertEqual(n2j(10), "")
self.assertEqual(n2j(10, reading=True), "じゅう")
self.assertEqual(n2j(11), "十一")
self.assertEqual(n2j(11, reading=True), "じゅういち")
self.assertEqual(n2j(12), "十二")
self.assertEqual(n2j(12, reading=True), "じゅうに")
self.assertEqual(n2j(13), "十三")
self.assertEqual(n2j(13, reading=True), "じゅうさん")
self.assertEqual(n2j(14), "十四")
self.assertEqual(n2j(14, reading=True), "じゅうよん")
self.assertEqual(n2j(14, reading=True, prefer=[""]), "じゅうし")
self.assertEqual(n2j(15), "十五")
self.assertEqual(n2j(15, reading=True), "じゅうご")
self.assertEqual(n2j(16), "十六")
self.assertEqual(n2j(16, reading=True), "じゅうろく")
self.assertEqual(n2j(17), "十七")
self.assertEqual(n2j(17, reading=True), "じゅうなな")
self.assertEqual(n2j(17, reading=True, prefer=["しち"]), "じゅうしち")
self.assertEqual(n2j(18), "十八")
self.assertEqual(n2j(18, reading=True), "じゅうはち")
self.assertEqual(n2j(19), "十九")
self.assertEqual(n2j(19, reading=True), "じゅうきゅう")
self.assertEqual(n2j(20), "二十")
self.assertEqual(n2j(20, reading=True), "にじゅう")
def test_mid(self):
self.assertEqual(n2j(100), "")
self.assertEqual(n2j(100, reading=True), "ひゃく")
self.assertEqual(n2j(123), "百二十三")
self.assertEqual(n2j(123, reading=True), "ひゃくにじゅうさん")
self.assertEqual(n2j(300), "三百")
self.assertEqual(n2j(300, reading=True), "さんびゃく")
self.assertEqual(n2j(400), "四百")
self.assertEqual(n2j(400, reading=True), "よんひゃく")
# 400 --> しひゃく sounds weird, but can be generated with prefer
self.assertEqual(n2j(600), "六百")
self.assertEqual(n2j(600, reading=True), "ろっぴゃく")
self.assertEqual(n2j(700, reading=True, prefer=["しち"]), "しちひゃく")
self.assertEqual(n2j(800, reading=True), "はっぴゃく")
self.assertEqual(n2j(1000), "")
self.assertEqual(n2j(1000, reading=True), "せん")
self.assertEqual(n2j(3000, reading=True), "さんぜん")
self.assertEqual(n2j(8000, reading=True), "はっせん")
def test_high(self):
self.assertEqual(n2j(10000), "一万")
self.assertEqual(n2j(10000, reading=True), "いちまん")
self.assertEqual(n2j(12345), "一万二千三百四十五")
self.assertEqual(n2j(12345, reading=True),
"いちまん"
"にせん"
"さんびゃく"
"よんじゅうご")
self.assertEqual(n2j(10**8), "一億")
self.assertEqual(n2j(10**8, reading=True), "いちおく")
self.assertEqual(n2j(123456789), "一億二千三百四十五万六千七百八十九")
self.assertEqual(n2j(123456789, reading=True),
"いちおく"
"にせんさんびゃくよんじゅうごまん"
"ろくせんななひゃく"
"はちじゅうきゅう")
self.assertEqual(n2j(10**12), "一兆")
self.assertEqual(n2j(10**12, reading=True), "いっちょう")
self.assertEqual(n2j(1234567890123),
"一兆二千三百四十五億六千七百八十九万百二十三")
self.assertEqual(n2j(1234567890123, reading=True),
"いっちょう"
"にせんさんびゃくよんじゅうごおく"
"ろくせんななひゃくはちじゅうきゅうまん"
"ひゃくにじゅうさん")
# TODO: tests for 10**16 and above
def test_cardinal_float(self):
self.assertEqual(n2j(0.0123456789, prefer=[""]),
"〇点〇一二三四五六七八九")
self.assertEqual(n2j(0.0123456789, reading=True),
"れいてん"
"れいいち"
"にさん"
"よんご"
"ろくなな"
"はちきゅう")
self.assertEqual(n2j(10**8 + 0.01), "一億点零一")
self.assertEqual(n2j(10**8 + 0.01, reading=True),
"いちおくてんれいいち")
def test_ordinal(self):
self.assertEqual(n2j(0, to="ordinal"), "零番目")
self.assertEqual(n2j(0, to="ordinal", reading=True, prefer=["れい"]),
"れいばんめ")
self.assertEqual(n2j(2, to="ordinal", counter=""), "二人目")
self.assertEqual(n2j(3, to="ordinal", counter=""), "三つ目")
with self.assertRaises(NotImplementedError):
n2j(4, to="ordinal", reading=True, counter="")
def test_ordinal_num(self):
self.assertEqual(n2j(0, to="ordinal_num"), "0番目")
self.assertEqual(n2j(0, to="ordinal_num", reading=True), "0ばんめ")
self.assertEqual(n2j(2, to="ordinal_num", counter=""), "2人目")
self.assertEqual(n2j(3, to="ordinal_num", counter=""), "3つ目")
def test_currency(self):
self.assertEqual(n2j(123456789, to="currency"),
"一億二千三百四十五万六千七百八十九円")
self.assertEqual(n2j(123456789, to="currency", reading=True),
"いちおく"
"にせんさんびゃくよんじゅうごまん"
"ろくせんななひゃく"
"はちじゅうきゅうえん")
def test_year(self):
self.assertEqual(n2j(2017, to="year"), "平成二十九年")
self.assertEqual(n2j(2017, to="year", reading=True),
"へいせいにじゅうくねん")
self.assertEqual(n2j(2017, to="year", reading="arabic"),
"平成29年")
self.assertEqual(n2j(2009, to="year", era=False), "二千九年")
self.assertEqual(n2j(2009, to="year", reading=True, era=False),
"にせんくねん")
self.assertEqual(n2j(2000, to="year", era=False), "二千年")
self.assertEqual(n2j(2000, to="year", era=False, reading=True),
"にせんねん")
self.assertEqual(n2j(645, to="year"), "大化元年")
self.assertEqual(n2j(645, to="year", reading=True), "たいかがんねん")
self.assertEqual(n2j(645, to="year"), "大化元年")
self.assertEqual(n2j(645, to="year", reading=True), "たいかがんねん")
self.assertEqual(n2j(-99, to="year", era=False), "紀元前九十九年")
self.assertEqual(n2j(-99, to="year", era=False, reading=True),
"きげんぜんきゅうじゅうくねん")
self.assertEqual(n2j(1375, to="year"), "天授元年")
self.assertEqual(n2j(1375, to="year", prefer=["えいわ"]), "永和元年")

93
tests/test_ko.py Normal file
View File

@ -0,0 +1,93 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import division, print_function, unicode_literals
from unittest import TestCase
from num2words import num2words
def n2k(*args, **kwargs):
return num2words(*args, lang='ko', **kwargs)
class Num2WordsKOTest(TestCase):
def test_low(self):
cases = [(0, ""), (1, ""), (2, ""), (3, ""), (4, ""), (5, ""),
(6, ""), (7, ""), (8, ""), (9, ""), (10, ""),
(11, "십일"), (12, "십이"), (13, "십삼"), (14, "십사"),
(15, "십오"), (16, "십육"), (17, "십칠"),
(18, "십팔"), (19, "십구"), (20, "이십"), (25, "이십오"),
(31, "삼십일"), (42, "사십이"), (54, "오십사"), (63, "육십삼"),
(76, "칠십육"), (89, "팔십구"), (98, "구십팔")]
for num, out in cases:
self.assertEqual(n2k(num), out)
def test_mid(self):
cases = [(100, ""), (121, "백이십일"), (160, "백육십"), (256, "이백오십육"),
(285, "이백팔십오"), (486, "사백팔십육"), (627, "육백이십칠"),
(808, "팔백팔"), (999, "구백구십구"), (1004, "천사"),
(2018, "이천십팔"), (7063, "칠천육십삼")]
for num, out in cases:
self.assertEqual(n2k(num), out)
def test_high(self):
cases = [(10000, ""), (11020, "만 천이십"), (25891, "이만 오천팔백구십일"),
(64237, "육만 사천이백삼십칠"), (241572, "이십사만 천오백칠십이"),
(100000000, "일억"), (5000500000000, "오조 오억")]
for num, out in cases:
self.assertEqual(n2k(num), out)
def test_negative(self):
cases = [(-11, "마이너스 십일"), (-15, "마이너스 십오"),
(-18, "마이너스 십팔"), (-241572, "마이너스 이십사만 천오백칠십이")]
for num, out in cases:
self.assertEqual(n2k(num), out)
def test_year(self):
cases = [(2000, "이천년"), (2002, "이천이년"), (2018, "이천십팔년"),
(1954, "천구백오십사년"), (1910, "천구백십년"), (-1000, "기원전 천년")]
for num, out in cases:
self.assertEqual(n2k(num, to="year"), out)
def test_currency(self):
cases_krw = [(8350, "팔천삼백오십원"), (14980, "만사천구백팔십원"),
(250004000, "이억오천만사천원")]
cases_usd = [(4, "사달러 영센트"), (19.55, "십구달러 오십오센트")]
cases_jpy = [(15, "십오엔"), (50, "오십엔")]
for num, out in cases_krw:
self.assertEqual(n2k(num, to="currency"), out)
for num, out in cases_usd:
self.assertEqual(n2k(num, to="currency", currency="USD"), out)
for num, out in cases_jpy:
self.assertEqual(n2k(num, to="currency", currency="JPY"), out)
with self.assertRaises(ValueError):
n2k(190.55, to="currency")
with self.assertRaises(NotImplementedError):
n2k(4, to="currency", currency="EUR")
def test_ordinal(self):
cases = [(1, "첫 번째"), (101, "백 한 번째"), (2, "두 번째"), (5, "다섯 번째"),
(10, "열 번째"), (25, "스물다섯 번째"), (137, "백 서른일곱 번째")]
for num, out in cases:
self.assertEqual(n2k(num, to="ordinal"), out)
def test_ordinal_num(self):
cases = [(1, "1 번째"), (101, "101 번째"), (25, "25 번째")]
for num, out in cases:
self.assertEqual(n2k(num, to="ordinal_num"), out)

178
tests/test_lt.py Normal file
View File

@ -0,0 +1,178 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
class Num2WordsLTTest(TestCase):
def test_to_cardinal(self):
self.assertEqual(num2words(100, lang='lt'), 'vienas šimtas')
self.assertEqual(num2words(101, lang='lt'), 'vienas šimtas vienas')
self.assertEqual(num2words(110, lang='lt'), 'vienas šimtas dešimt')
self.assertEqual(num2words(115, lang='lt'),
'vienas šimtas penkiolika')
self.assertEqual(num2words(123, lang='lt'),
'vienas šimtas dvidešimt trys')
self.assertEqual(num2words(1000, lang='lt'), 'vienas tūkstantis')
self.assertEqual(num2words(1001, lang='lt'),
'vienas tūkstantis vienas')
self.assertEqual(num2words(2012, lang='lt'),
'du tūkstančiai dvylika')
self.assertEqual(
num2words(1234567890, lang='lt'),
"vienas milijardas du šimtai trisdešimt keturi milijonai "
"penki šimtai šešiasdešimt septyni tūkstančiai aštuoni šimtai "
"devyniasdešimt")
self.assertEqual(
num2words(215461407892039002157189883901676, lang='lt'),
"du šimtai penkiolika naintilijonų keturi šimtai šešiasdešimt "
"vienas oktilijonas keturi šimtai septyni septilijonai aštuoni "
"šimtai devyniasdešimt du sikstilijonai trisdešimt devyni "
"kvintilijonai du kvadrilijonai vienas šimtas penkiasdešimt "
"septyni trilijonai vienas šimtas aštuoniasdešimt devyni "
"milijardai aštuoni šimtai aštuoniasdešimt trys milijonai "
"devyni šimtai vienas tūkstantis šeši šimtai "
"septyniasdešimt šeši")
self.assertEqual(
num2words(719094234693663034822824384220291, lang='lt'),
"septyni šimtai devyniolika naintilijonų devyniasdešimt keturi "
"oktilijonai du šimtai trisdešimt keturi septilijonai šeši "
"šimtai devyniasdešimt trys sikstilijonai šeši šimtai "
"šešiasdešimt trys kvintilijonai trisdešimt keturi kvadrilijonai "
"aštuoni šimtai dvidešimt du trilijonai aštuoni šimtai dvidešimt "
"keturi milijardai trys šimtai aštuoniasdešimt keturi milijonai "
"du šimtai dvidešimt tūkstančių du šimtai devyniasdešimt vienas")
self.assertEqual(
num2words(-5000, lang='lt'),
'minus penki tūkstančiai',
)
self.assertEqual(
num2words(-5000.22, lang='lt'),
'minus penki tūkstančiai kablelis dvidešimt du',
)
def test_to_ordinal(self):
# @TODO: implement to_ordinal
with self.assertRaises(NotImplementedError):
num2words(1, lang='lt', to='ordinal')
def test_to_currency(self):
# Test all available currency forms.
# LTL
self.assertEqual(
num2words(1.0, lang='lt', to='currency', currency='LTL'),
'vienas litas, nulis centų'
)
self.assertEqual(
num2words(10.01, lang='lt', to='currency', currency='LTL'),
'dešimt litų, vienas centas'
)
self.assertEqual(
num2words(1234.56, lang='lt', to='currency', currency='LTL'),
'vienas tūkstantis du šimtai trisdešimt keturi litai, '
'penkiasdešimt šeši centai'
)
# EUR
self.assertEqual(
num2words(-1251981, lang='lt', to='currency', currency='EUR',
cents=False),
'minus dvylika tūkstančių penki šimtai devyniolika eurų, '
'81 centas'
)
self.assertEqual(
num2words(1.0, lang='lt', to='currency', currency='EUR'),
'vienas euras, nulis centų'
)
self.assertEqual(
num2words(1234.56, lang='lt', to='currency', currency='EUR'),
'vienas tūkstantis du šimtai trisdešimt keturi eurai, '
'penkiasdešimt šeši centai'
)
self.assertEqual(
num2words(1122.22, lang='lt', to='currency', currency='EUR'),
'vienas tūkstantis vienas šimtas dvidešimt du eurai, '
'dvidešimt du centai'
)
# USD
self.assertEqual(
num2words(-1281, lang='lt', to='currency', currency='USD',
cents=False),
'minus dvylika dolerių, 81 centas'
)
self.assertEqual(
num2words(1.0, lang='lt', to='currency', currency='USD'),
'vienas doleris, nulis centų'
)
self.assertEqual(
num2words(5.06, lang='lt', to='currency', currency='USD'),
'penki doleriai, šeši centai'
)
# GBP
self.assertEqual(
num2words(-1281, lang='lt', to='currency', currency='GBP',
cents=False),
'minus dvylika svarų sterlingų, 81 pensas'
)
self.assertEqual(
num2words(1.0, lang='lt', to='currency', currency='GBP'),
'vienas svaras sterlingų, nulis pensų'
)
self.assertEqual(
num2words(5.06, lang='lt', to='currency', currency='GBP'),
'penki svarai sterlingų, šeši pensai'
)
# PLN
self.assertEqual(
num2words(-1281, lang='lt', to='currency', currency='PLN',
cents=False),
'minus dvylika zlotų, 81 grašis'
)
self.assertEqual(
num2words(1.0, lang='lt', to='currency', currency='PLN'),
'vienas zlotas, nulis grašių'
)
self.assertEqual(
num2words(5.06, lang='lt', to='currency', currency='PLN'),
'penki zlotai, šeši grašiai'
)
# RUB
self.assertEqual(
num2words(-1281, lang='lt', to='currency', currency='RUB',
cents=False),
'minus dvylika rublių, 81 kapeika'
)
self.assertEqual(
num2words(1.0, lang='lt', to='currency', currency='RUB'),
'vienas rublis, nulis kapeikų'
)
self.assertEqual(
num2words(5.06, lang='lt', to='currency', currency='RUB'),
'penki rubliai, šešios kapeikos'
)
self.assertEqual(
num2words(-12.01, lang='lt', to='currency', currency='RUB'),
'minus dvylika rublių, viena kapeika'
)
self.assertEqual(
num2words(1122.22, lang='lt', to='currency', currency='RUB'),
'vienas tūkstantis vienas šimtas dvidešimt du rubliai, '
'dvidešimt dvi kapeikos'
)

154
tests/test_lv.py Normal file
View File

@ -0,0 +1,154 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
class Num2WordsLVTest(TestCase):
def test_to_cardinal(self):
self.assertEqual(num2words(100, lang='lv'), 'simts')
self.assertEqual(num2words(101, lang='lv'), 'simtu viens')
self.assertEqual(num2words(110, lang='lv'), 'simts desmit')
self.assertEqual(num2words(115, lang='lv'), 'simts piecpadsmit')
self.assertEqual(num2words(123, lang='lv'), 'simts divdesmit trīs')
self.assertEqual(num2words(1000, lang='lv'), 'tūkstotis')
self.assertEqual(num2words(1001, lang='lv'), 'tūkstotis viens')
self.assertEqual(num2words(2012, lang='lv'),
'divi tūkstoši divpadsmit')
self.assertEqual(
num2words(1234567890, lang='lv'),
'miljards divi simti trīsdesmit četri miljoni pieci simti '
'sešdesmit septiņi tūkstoši astoņi simti deviņdesmit')
self.assertEqual(
num2words(215461407892039002157189883901676, lang='lv'),
'divi simti piecpadsmit nontiljoni četri simti sešdesmit '
'viens oktiljons četri simti septiņi septiljoni astoņi '
'simti deviņdesmit divi sikstiljoni trīsdesmit deviņi '
'kvintiljoni divi kvadriljoni simts piecdesmit septiņi '
'triljoni simts astoņdesmit deviņi miljardi astoņi simti '
'astoņdesmit trīs miljoni deviņi simti viens tūkstotis '
'seši simti septiņdesmit seši')
self.assertEqual(
num2words(719094234693663034822824384220291, lang='lv'),
'septiņi simti deviņpadsmit nontiljoni deviņdesmit četri '
'oktiljoni divi simti trīsdesmit četri septiljoni seši simti '
'deviņdesmit trīs sikstiljoni seši simti sešdesmit trīs '
'kvintiljoni trīsdesmit četri kvadriljoni astoņi simti '
'divdesmit divi triljoni astoņi simti divdesmit četri '
'miljardi trīs simti astoņdesmit četri miljoni divi simti '
'divdesmit tūkstoši divi simti deviņdesmit viens')
self.assertEqual(
num2words(-5000, lang='lv'),
'mīnus pieci tūkstoši',
)
self.assertEqual(
num2words(-5000.22, lang='lv'),
'mīnus pieci tūkstoši komats divdesmit divi',
)
self.assertEqual(num2words(0, lang='lv'), 'nulle')
self.assertEqual(num2words(5, lang='lv'), "pieci")
self.assertEqual(num2words(15, lang='lv'), "piecpadsmit")
self.assertEqual(num2words(154, lang='lv'), "simts piecdesmit četri")
self.assertEqual(num2words(101, lang='lv'), "simtu viens")
self.assertEqual(
num2words(1135, lang='lv'), "tūkstotis simts trīsdesmit pieci"
)
self.assertEqual(
num2words(418531, lang='lv'),
"četri simti astoņpadsmit tūkstoši pieci simti trīsdesmit viens"
)
self.assertEqual(
num2words(1000139, lang='lv'),
"miljons simts trīsdesmit deviņi"
)
def test_to_ordinal(self):
# @TODO: implement to_ordinal
with self.assertRaises(NotImplementedError):
num2words(1, lang='lv', to='ordinal')
def test_to_currency(self):
self.assertEqual(
num2words(1.0, lang='lv', to='currency', currency='EUR'),
"viens eiro, nulle centu"
)
self.assertEqual(
num2words(1.0, lang='lv', to='currency', currency='LVL'),
"viens lats, nulle santīmu"
)
self.assertEqual(
num2words(1234.56, lang='lv', to='currency', currency='EUR'),
"tūkstotis divi simti trīsdesmit četri eiro, piecdesmit seši centi"
)
self.assertEqual(
num2words(1234.56, lang='lv', to='currency', currency='LVL'),
"tūkstotis divi simti trīsdesmit četri lati, "
"piecdesmit seši santīmi"
)
self.assertEqual(
num2words(10111, lang='lv', to='currency', seperator=' un',
currency='EUR'),
"simtu viens eiro un vienpadsmit centi"
)
self.assertEqual(
num2words(10121, lang='lv', to='currency', seperator=' un',
currency='LVL'),
"simtu viens lats un divdesmit viens santīms"
)
self.assertEqual(
num2words(-1251985, lang='lv', to='currency', cents=False,
currency='EUR'),
"mīnus divpadsmit tūkstoši pieci simti deviņpadsmit eiro,"
" 85 centi"
)
self.assertEqual(
num2words('38.4', lang='lv', to='currency', seperator=' un',
cents=False, currency='EUR'),
"trīsdesmit astoņi eiro un 40 centi"
)
# EUR legal form
self.assertEqual(
num2words('38.4', lang='lv', to='currency', seperator=' un',
cents=False, currency='EUR_LEGAL'),
"trīsdesmit astoņi euro un 40 centi"
)
self.assertEqual(
num2words('38.4', lang='lv', to='currency', seperator=' un',
cents=False, currency='USD', adjective=False),
"trīsdesmit astoņi dolāri un 40 centi"
)
self.assertEqual(
num2words('38.4', lang='lv', to='currency', seperator=' un',
cents=False, currency='USD', adjective=True),
"trīsdesmit astoņi ASV dolāri un 40 centi"
)
def test_fractions(self):
self.assertEqual(num2words(5.2, lang='lv'), "pieci komats divi")
self.assertEqual(
num2words(561.42, lang='lv'),
"pieci simti sešdesmit viens komats četrdesmit divi"
)

108
tests/test_nl.py Normal file
View File

@ -0,0 +1,108 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
from num2words.lang_NL import Num2Word_NL
class Num2WordsNLTest(TestCase):
def test_ordinal_less_than_twenty(self):
self.assertEqual(num2words(7, ordinal=True, lang='nl'), "zevende")
self.assertEqual(num2words(8, ordinal=True, lang='nl'), "achtste")
self.assertEqual(num2words(12, ordinal=True, lang='nl'), "twaalfde")
self.assertEqual(num2words(17, ordinal=True, lang='nl'), "zeventiende")
def test_ordinal_more_than_twenty(self):
self.assertEqual(
num2words(81, ordinal=True, lang='nl'), "eenentachtigste"
)
def test_ordinal_at_crucial_number(self):
self.assertEqual(num2words(100, ordinal=True, lang='nl'), "honderdste")
self.assertEqual(
num2words(1000, ordinal=True, lang='nl'), "duizendste"
)
self.assertEqual(
num2words(4000, ordinal=True, lang='nl'), "vierduizendste"
)
self.assertEqual(
num2words(2000000, ordinal=True, lang='nl'), "twee miljoenste"
)
self.assertEqual(
num2words(5000000000, ordinal=True, lang='nl'), "vijf miljardste"
)
def test_cardinal_at_some_numbers(self):
self.assertEqual(num2words(82, lang='nl'), u'twee\xebntachtig')
self.assertEqual(num2words(1013, lang='nl'), "duizenddertien")
self.assertEqual(num2words(2000000, lang='nl'), "twee miljoen")
self.assertEqual(num2words(4000000000, lang='nl'), "vier miljard")
def test_cardinal_for_decimal_number(self):
self.assertEqual(
num2words(3.486, lang='nl'), "drie komma vier acht zes"
)
def test_ordinal_for_negative_numbers(self):
self.assertRaises(TypeError, num2words, -12, ordinal=True, lang='nl')
def test_ordinal_for_floating_numbers(self):
self.assertRaises(TypeError, num2words, 2.453, ordinal=True, lang='nl')
def test_to_currency(self):
self.assertEqual(
num2words('38.4', lang='nl', to='currency', seperator=' en',
cents=False, currency='EUR'),
"achtendertig euro en 40 cent"
)
self.assertEqual(
num2words('0', lang='nl', to='currency', seperator=' en',
cents=False, currency='EUR'),
"nul euro en 00 cent"
)
self.assertEqual(
num2words('1.01', lang='nl', to='currency', seperator=' en',
cents=True, currency='EUR'),
"één euro en één cent"
)
self.assertEqual(
num2words('4778.00', lang='nl', to='currency', seperator=' en',
cents=True, currency='EUR'),
'vierduizendzevenhonderdachtenzeventig euro en nul cent')
def test_pluralize(self):
n = Num2Word_NL()
# euros always singular
cr1, cr2 = n.CURRENCY_FORMS['EUR']
self.assertEqual(n.pluralize(1, cr1), 'euro')
self.assertEqual(n.pluralize(2, cr1), 'euro')
self.assertEqual(n.pluralize(1, cr2), 'cent')
self.assertEqual(n.pluralize(2, cr2), 'cent')
# @TODO other currency
def test_to_year(self):
self.assertEqual(num2words(2018, lang='nl', to='year'),
'tweeduizendachttien')
self.assertEqual(num2words(2100, lang='nl', to='year'),
'eenentwintig honderd')

129
tests/test_pl.py Normal file
View File

@ -0,0 +1,129 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
class Num2WordsPLTest(TestCase):
def test_cardinal(self):
self.assertEqual(num2words(100, lang='pl'), "sto")
self.assertEqual(num2words(101, lang='pl'), "sto jeden")
self.assertEqual(num2words(110, lang='pl'), "sto dziesięć")
self.assertEqual(num2words(115, lang='pl'), "sto piętnaście")
self.assertEqual(num2words(123, lang='pl'), "sto dwadzieścia trzy")
self.assertEqual(num2words(1000, lang='pl'), "tysiąc")
self.assertEqual(num2words(1001, lang='pl'), "tysiąc jeden")
self.assertEqual(num2words(2012, lang='pl'), "dwa tysiące dwanaście")
self.assertEqual(
num2words(12519.85, lang='pl'),
"dwanaście tysięcy pięćset dziewiętnaście przecinek "
"osiemdziesiąt pięć"
)
self.assertEqual(
num2words(123.50, lang='pl'),
"sto dwadzieścia trzy przecinek pięć"
)
self.assertEqual(
num2words(1234567890, lang='pl'),
"miliard dwieście trzydzieści cztery miliony pięćset "
"sześćdziesiąt siedem tysięcy osiemset dziewięćdzisiąt"
)
self.assertEqual(
num2words(10000000001000000100000, lang='pl'),
"dziesięć tryliardów bilion sto tysięcy"
)
self.assertEqual(
num2words(215461407892039002157189883901676, lang='pl'),
"dwieście piętnaście kwintylionów czterysta sześćdziesiąt jeden "
"kwadryliardów czterysta siedem kwadrylionów osiemset "
"dziewięćdzisiąt dwa tryliardy trzydzieści dziewięć trylionów "
"dwa biliardy sto pięćdziesiąt siedem bilionów sto osiemdziesiąt "
"dziewięć miliardów osiemset osiemdziesiąt trzy miliony "
"dziewięćset jeden tysięcy sześćset siedemdziesiąt sześć"
)
self.assertEqual(
num2words(719094234693663034822824384220291, lang='pl'),
"siedemset dziewiętnaście kwintylionów dziewięćdzisiąt cztery "
"kwadryliardy dwieście trzydzieści cztery kwadryliony sześćset "
"dziewięćdzisiąt trzy tryliardy sześćset sześćdziesiąt trzy "
"tryliony trzydzieści cztery biliardy osiemset dwadzieścia dwa "
"biliony osiemset dwadzieścia cztery miliardy trzysta "
"osiemdziesiąt cztery miliony dwieście dwadzieścia "
"tysięcy dwieście dziewięćdzisiąt jeden"
)
self.assertEqual(
num2words(
963301000001918264129471001047146102 * 10**30 + 1007,
lang='pl'
),
"dziewięćset sześćdziesiąt trzy decyliardy trzysta jeden "
"decylionów nonylion dziewięćset osiemnaście oktyliardów dwieście "
"sześćdziesiąt cztery oktyliony sto dwadzieścia dziewięć "
"septyliardów czterysta siedemdziesiąt jeden septylionów "
"sekstyliard czterdzieści siedem sekstylionów sto czterdzieści "
"sześć kwintyliardów sto dwa kwintyliony tysiąc siedem"
)
def test_to_ordinal(self):
# @TODO: implement to_ordinal
with self.assertRaises(NotImplementedError):
num2words(1, lang='pl', to='ordinal')
def test_currency(self):
self.assertEqual(
num2words(1.0, lang='pl', to='currency', currency='EUR'),
"jeden euro, zero centów")
self.assertEqual(
num2words(1.0, lang='pl', to='currency', currency='PLN'),
"jeden złoty, zero groszy")
self.assertEqual(
num2words(1234.56, lang='pl', to='currency', currency='EUR'),
"tysiąc dwieście trzydzieści cztery euro, pięćdziesiąt sześć "
"centów"
)
self.assertEqual(
num2words(1234.56, lang='pl', to='currency', currency='PLN'),
"tysiąc dwieście trzydzieści cztery złote, pięćdziesiąt sześć "
"groszy"
)
self.assertEqual(
num2words(10111, lang='pl', to='currency', currency='EUR',
seperator=' i'),
"sto jeden euro i jedenaście centów"
)
self.assertEqual(
num2words(10121, lang='pl', to='currency', currency='PLN',
seperator=' i'),
"sto jeden złotych i dwadzieścia jeden groszy"
)
self.assertEqual(
num2words(-1251985, lang='pl', to='currency', cents=False),
"minus dwanaście tysięcy pięćset dziewiętnaście euro, 85 centów"
)
self.assertEqual(
num2words(123.50, lang='pl', to='currency', currency='PLN',
seperator=' i'),
"sto dwadzieścia trzy złote i pięćdziesiąt groszy"
)
self.assertEqual(
num2words(1950, lang='pl', to='currency', cents=False),
"dziewiętnaście euro, 50 centów"
)

455
tests/test_pt.py Normal file
View File

@ -0,0 +1,455 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from decimal import Decimal
from unittest import TestCase
from num2words import num2words
from num2words.lang_PT import Num2Word_PT
class Num2WordsPTTest(TestCase):
def setUp(self):
super(Num2WordsPTTest, self).setUp()
self.n2w = Num2Word_PT()
def test_cardinal_integer(self):
self.assertEqual(num2words(1, lang='pt'), 'um')
self.assertEqual(num2words(2, lang='pt'), 'dois')
self.assertEqual(num2words(3, lang='pt'), 'três')
self.assertEqual(num2words(4, lang='pt'), 'quatro')
self.assertEqual(num2words(5, lang='pt'), 'cinco')
self.assertEqual(num2words(6, lang='pt'), 'seis')
self.assertEqual(num2words(7, lang='pt'), 'sete')
self.assertEqual(num2words(8, lang='pt'), 'oito')
self.assertEqual(num2words(9, lang='pt'), 'nove')
self.assertEqual(num2words(10, lang='pt'), 'dez')
self.assertEqual(num2words(11, lang='pt'), 'onze')
self.assertEqual(num2words(12, lang='pt'), 'doze')
self.assertEqual(num2words(13, lang='pt'), 'treze')
self.assertEqual(num2words(14, lang='pt'), 'catorze')
self.assertEqual(num2words(15, lang='pt'), 'quinze')
self.assertEqual(num2words(16, lang='pt'), 'dezasseis')
self.assertEqual(num2words(17, lang='pt'), 'dezassete')
self.assertEqual(num2words(18, lang='pt'), 'dezoito')
self.assertEqual(num2words(19, lang='pt'), 'dezanove')
self.assertEqual(num2words(20, lang='pt'), 'vinte')
self.assertEqual(num2words(21, lang='pt'), 'vinte e um')
self.assertEqual(num2words(22, lang='pt'), 'vinte e dois')
self.assertEqual(num2words(35, lang='pt'), 'trinta e cinco')
self.assertEqual(num2words(99, lang='pt'), 'noventa e nove')
self.assertEqual(num2words(100, lang='pt'), 'cem')
self.assertEqual(num2words(101, lang='pt'), 'cento e um')
self.assertEqual(num2words(128, lang='pt'), 'cento e vinte e oito')
self.assertEqual(num2words(713, lang='pt'), 'setecentos e treze')
self.assertEqual(num2words(1000, lang='pt'), 'mil')
self.assertEqual(num2words(1001, lang='pt'), 'mil e um')
self.assertEqual(num2words(1111, lang='pt'), 'mil cento e onze')
self.assertEqual(
num2words(2114, lang='pt'), 'dois mil cento e catorze'
)
self.assertEqual(
num2words(2200, lang='pt'),
'dois mil e duzentos'
)
self.assertEqual(
num2words(2230, lang='pt'),
'dois mil duzentos e trinta'
)
self.assertEqual(
num2words(73400, lang='pt'),
'setenta e três mil e quatrocentos'
)
self.assertEqual(
num2words(73421, lang='pt'),
'setenta e três mil quatrocentos e vinte e um'
)
self.assertEqual(num2words(100000, lang='pt'), 'cem mil')
self.assertEqual(
num2words(250050, lang='pt'),
'duzentos e cinquenta mil e cinquenta'
)
self.assertEqual(
num2words(6000000, lang='pt'), 'seis milhões'
)
self.assertEqual(
num2words(100000000, lang='pt'), 'cem milhões'
)
self.assertEqual(
num2words(19000000000, lang='pt'), 'dezanove mil milhões'
)
self.assertEqual(
num2words(145000000002, lang='pt'),
'cento e quarenta e cinco mil milhões e dois'
)
self.assertEqual(
num2words(4635102, lang='pt'),
'quatro milhões seiscentos e trinta e cinco mil cento e dois'
)
self.assertEqual(
num2words(145254635102, lang='pt'),
'cento e quarenta e cinco mil duzentos e cinquenta e quatro '
'milhões seiscentos e trinta e cinco mil cento e dois'
)
self.assertEqual(
num2words(1000000000000, lang='pt'),
'um bilião'
)
self.assertEqual(
num2words(2000000000000, lang='pt'),
'dois biliões'
)
self.assertEqual(
num2words(1000000000000000, lang='pt'),
'mil biliões'
)
self.assertEqual(
num2words(2000000000000000, lang='pt'),
'dois mil biliões'
)
self.assertEqual(
num2words(1000000000000000000, lang='pt'),
'um trilião'
)
self.assertEqual(
num2words(2000000000000000000, lang='pt'),
'dois triliões'
)
def test_cardinal_integer_negative(self):
self.assertEqual(num2words(-1, lang='pt'), 'menos um')
self.assertEqual(
num2words(-256, lang='pt'), 'menos duzentos e cinquenta e seis'
)
self.assertEqual(num2words(-1000, lang='pt'), 'menos mil')
self.assertEqual(num2words(-1000000, lang='pt'), 'menos um milhão')
self.assertEqual(
num2words(-1234567, lang='pt'),
'menos um milhão duzentos e trinta e quatro mil quinhentos e '
'sessenta e sete'
)
def test_cardinal_float(self):
self.assertEqual(num2words(Decimal('1.00'), lang='pt'), 'um')
self.assertEqual(num2words(
Decimal('1.01'), lang='pt'), 'um vírgula zero um')
self.assertEqual(num2words(
Decimal('1.035'), lang='pt'), 'um vírgula zero três cinco'
)
self.assertEqual(num2words(
Decimal('1.35'), lang='pt'), 'um vírgula três cinco'
)
self.assertEqual(
num2words(Decimal('3.14159'), lang='pt'),
'três vírgula um quatro um cinco nove'
)
self.assertEqual(
num2words(Decimal('101.22'), lang='pt'),
'cento e um vírgula dois dois'
)
self.assertEqual(
num2words(Decimal('2345.75'), lang='pt'),
'dois mil trezentos e quarenta e cinco vírgula sete cinco')
def test_cardinal_float_negative(self):
self.assertEqual(
num2words(Decimal('-2.34'), lang='pt'),
'menos dois vírgula três quatro'
)
self.assertEqual(
num2words(Decimal('-9.99'), lang='pt'),
'menos nove vírgula nove nove'
)
self.assertEqual(
num2words(Decimal('-7.01'), lang='pt'),
'menos sete vírgula zero um'
)
self.assertEqual(
num2words(Decimal('-222.22'), lang='pt'),
'menos duzentos e vinte e dois vírgula dois dois'
)
def test_ordinal(self):
self.assertEqual(num2words(1, lang='pt', ordinal=True), 'primeiro')
self.assertEqual(num2words(2, lang='pt', ordinal=True), 'segundo')
self.assertEqual(num2words(3, lang='pt', ordinal=True), 'terceiro')
self.assertEqual(num2words(4, lang='pt', ordinal=True), 'quarto')
self.assertEqual(num2words(5, lang='pt', ordinal=True), 'quinto')
self.assertEqual(num2words(6, lang='pt', ordinal=True), 'sexto')
self.assertEqual(num2words(7, lang='pt', ordinal=True), 'sétimo')
self.assertEqual(num2words(8, lang='pt', ordinal=True), 'oitavo')
self.assertEqual(num2words(9, lang='pt', ordinal=True), 'nono')
self.assertEqual(num2words(10, lang='pt', ordinal=True), 'décimo')
self.assertEqual(
num2words(11, lang='pt', ordinal=True), 'décimo primeiro'
)
self.assertEqual(
num2words(12, lang='pt', ordinal=True), 'décimo segundo'
)
self.assertEqual(
num2words(13, lang='pt', ordinal=True), 'décimo terceiro'
)
self.assertEqual(
num2words(14, lang='pt', ordinal=True), 'décimo quarto'
)
self.assertEqual(
num2words(15, lang='pt', ordinal=True), 'décimo quinto'
)
self.assertEqual(
num2words(16, lang='pt', ordinal=True), 'décimo sexto'
)
self.assertEqual(
num2words(17, lang='pt', ordinal=True), 'décimo sétimo'
)
self.assertEqual(
num2words(18, lang='pt', ordinal=True), 'décimo oitavo'
)
self.assertEqual(
num2words(19, lang='pt', ordinal=True), 'décimo nono'
)
self.assertEqual(
num2words(20, lang='pt', ordinal=True), 'vigésimo'
)
self.assertEqual(
num2words(21, lang='pt', ordinal=True), 'vigésimo primeiro'
)
self.assertEqual(
num2words(22, lang='pt', ordinal=True), 'vigésimo segundo'
)
self.assertEqual(
num2words(35, lang='pt', ordinal=True), 'trigésimo quinto'
)
self.assertEqual(
num2words(99, lang='pt', ordinal=True), 'nonagésimo nono'
)
self.assertEqual(
num2words(100, lang='pt', ordinal=True), 'centésimo'
)
self.assertEqual(
num2words(101, lang='pt', ordinal=True), 'centésimo primeiro'
)
self.assertEqual(
num2words(128, lang='pt', ordinal=True),
'centésimo vigésimo oitavo'
)
self.assertEqual(
num2words(713, lang='pt', ordinal=True),
'septigentésimo décimo terceiro'
)
self.assertEqual(
num2words(1000, lang='pt', ordinal=True), 'milésimo'
)
self.assertEqual(
num2words(1001, lang='pt', ordinal=True), 'milésimo primeiro'
)
self.assertEqual(
num2words(1111, lang='pt', ordinal=True),
'milésimo centésimo décimo primeiro'
)
self.assertEqual(
num2words(2114, lang='pt', ordinal=True),
'segundo milésimo centésimo décimo quarto'
)
self.assertEqual(
num2words(73421, lang='pt', ordinal=True),
'septuagésimo terceiro milésimo quadrigentésimo vigésimo primeiro'
)
self.assertEqual(
num2words(100000, lang='pt', ordinal=True),
'centésimo milésimo'
)
self.assertEqual(
num2words(250050, lang='pt', ordinal=True),
'ducentésimo quinquagésimo milésimo quinquagésimo'
)
self.assertEqual(
num2words(6000000, lang='pt', ordinal=True), 'sexto milionésimo'
)
self.assertEqual(
num2words(19000000000, lang='pt', ordinal=True),
'décimo nono milésimo milionésimo'
)
self.assertEqual(
num2words(145000000002, lang='pt', ordinal=True),
'centésimo quadragésimo quinto milésimo milionésimo segundo'
)
def test_currency_integer(self):
self.assertEqual(self.n2w.to_currency(1.00), 'um euro')
self.assertEqual(self.n2w.to_currency(2.00), 'dois euros')
self.assertEqual(self.n2w.to_currency(3.00), 'três euros')
self.assertEqual(self.n2w.to_currency(4.00), 'quatro euros')
self.assertEqual(self.n2w.to_currency(5.00), 'cinco euros')
self.assertEqual(self.n2w.to_currency(6.00), 'seis euros')
self.assertEqual(self.n2w.to_currency(7.00), 'sete euros')
self.assertEqual(self.n2w.to_currency(8.00), 'oito euros')
self.assertEqual(self.n2w.to_currency(9.00), 'nove euros')
self.assertEqual(self.n2w.to_currency(10.00), 'dez euros')
self.assertEqual(self.n2w.to_currency(11.00), 'onze euros')
self.assertEqual(self.n2w.to_currency(12.00), 'doze euros')
self.assertEqual(self.n2w.to_currency(13.00), 'treze euros')
self.assertEqual(self.n2w.to_currency(14.00), 'catorze euros')
self.assertEqual(self.n2w.to_currency(15.00), 'quinze euros')
self.assertEqual(self.n2w.to_currency(16.00), 'dezasseis euros')
self.assertEqual(self.n2w.to_currency(17.00), 'dezassete euros')
self.assertEqual(self.n2w.to_currency(18.00), 'dezoito euros')
self.assertEqual(self.n2w.to_currency(19.00), 'dezanove euros')
self.assertEqual(self.n2w.to_currency(20.00), 'vinte euros')
self.assertEqual(self.n2w.to_currency(21.00), 'vinte e um euros')
self.assertEqual(self.n2w.to_currency(22.00), 'vinte e dois euros')
self.assertEqual(self.n2w.to_currency(35.00), 'trinta e cinco euros')
self.assertEqual(self.n2w.to_currency(99.00), 'noventa e nove euros')
self.assertEqual(self.n2w.to_currency(100.00), 'cem euros')
self.assertEqual(self.n2w.to_currency(101.00), 'cento e um euros')
self.assertEqual(
self.n2w.to_currency(128.00), 'cento e vinte e oito euros'
)
self.assertEqual(
self.n2w.to_currency(713.00), 'setecentos e treze euros')
self.assertEqual(self.n2w.to_currency(1000.00), 'mil euros')
self.assertEqual(self.n2w.to_currency(1001.00), 'mil e um euros')
self.assertEqual(
self.n2w.to_currency(1111.00), 'mil cento e onze euros')
self.assertEqual(
self.n2w.to_currency(2114.00), 'dois mil cento e catorze euros'
)
self.assertEqual(
self.n2w.to_currency(73421.00),
'setenta e três mil quatrocentos e vinte e um euros'
)
self.assertEqual(self.n2w.to_currency(100000.00), 'cem mil euros')
self.assertEqual(
self.n2w.to_currency(250050.00),
'duzentos e cinquenta mil e cinquenta euros'
)
self.assertEqual(
self.n2w.to_currency(6000000.00), 'seis milhões de euros'
)
self.assertEqual(
self.n2w.to_currency(19000000000.00),
'dezanove mil milhões de euros'
)
self.assertEqual(
self.n2w.to_currency(145000000002.00),
'cento e quarenta e cinco mil milhões e dois euros'
)
self.assertEqual(self.n2w.to_currency(1.00, currency='USD'),
'um dólar')
self.assertEqual(self.n2w.to_currency(1.50, currency='USD'),
'um dólar e cinquenta cêntimos')
with self.assertRaises(NotImplementedError):
self.n2w.to_currency(1.00, currency='CHF')
def test_currency_integer_negative(self):
self.assertEqual(self.n2w.to_currency(-1.00), 'menos um euro')
self.assertEqual(
self.n2w.to_currency(-256.00),
'menos duzentos e cinquenta e seis euros'
)
self.assertEqual(self.n2w.to_currency(-1000.00), 'menos mil euros')
self.assertEqual(
self.n2w.to_currency(-1000000.00), 'menos um milhão de euros'
)
self.assertEqual(
self.n2w.to_currency(-1234567.00),
'menos um milhão duzentos e trinta e quatro mil quinhentos e '
'sessenta e sete euros'
)
def test_currency_float(self):
self.assertEqual(self.n2w.to_currency(Decimal('1.00')), 'um euro')
self.assertEqual(
self.n2w.to_currency(Decimal('1.01')), 'um euro e um cêntimo'
)
self.assertEqual(
self.n2w.to_currency(Decimal('1.03')), 'um euro e três cêntimos'
)
self.assertEqual(
self.n2w.to_currency(Decimal('1.35')),
'um euro e trinta e cinco cêntimos'
)
self.assertEqual(
self.n2w.to_currency(Decimal('3.14')),
'três euros e catorze cêntimos'
)
self.assertEqual(
self.n2w.to_currency(Decimal('101.22')),
'cento e um euros e vinte e dois cêntimos'
)
self.assertEqual(
self.n2w.to_currency(Decimal('2345.75')),
'dois mil trezentos e quarenta e cinco euros e setenta e cinco '
'cêntimos'
)
def test_currency_float_negative(self):
self.assertEqual(
self.n2w.to_currency(Decimal('-2.34')),
'menos dois euros e trinta e quatro cêntimos'
)
self.assertEqual(
self.n2w.to_currency(Decimal('-9.99')),
'menos nove euros e noventa e nove cêntimos'
)
self.assertEqual(
self.n2w.to_currency(Decimal('-7.01')),
'menos sete euros e um cêntimo'
)
self.assertEqual(
self.n2w.to_currency(Decimal('-222.22')),
'menos duzentos e vinte e dois euros e vinte e dois cêntimos'
)
def test_year(self):
self.assertEqual(self.n2w.to_year(1001), 'mil e um')
self.assertEqual(
self.n2w.to_year(1789), 'mil setecentos e oitenta e nove'
)
self.assertEqual(
self.n2w.to_year(1942), 'mil novecentos e quarenta e dois'
)
self.assertEqual(
self.n2w.to_year(1984), 'mil novecentos e oitenta e quatro'
)
self.assertEqual(self.n2w.to_year(2000), 'dois mil')
self.assertEqual(self.n2w.to_year(2001), 'dois mil e um')
self.assertEqual(self.n2w.to_year(2016), 'dois mil e dezasseis')
def test_year_negative(self):
self.assertEqual(self.n2w.to_year(-30), 'trinta antes de Cristo')
self.assertEqual(
self.n2w.to_year(-744),
'setecentos e quarenta e quatro antes de Cristo'
)
self.assertEqual(self.n2w.to_year(-10000), 'dez mil antes de Cristo')
def test_to_ordinal_num(self):
self.assertEqual(self.n2w.to_ordinal_num(1), '')
self.assertEqual(self.n2w.to_ordinal_num(100), '100º')

395
tests/test_pt_BR.py Normal file
View File

@ -0,0 +1,395 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from decimal import Decimal
from unittest import TestCase
from num2words import num2words
from num2words.lang_PT_BR import Num2Word_PT_BR
class Num2WordsPTBRTest(TestCase):
def setUp(self):
super(Num2WordsPTBRTest, self).setUp()
self.n2w = Num2Word_PT_BR()
def test_cardinal_integer(self):
self.assertEqual(num2words(1, lang='pt_BR'), 'um')
self.assertEqual(num2words(2, lang='pt_BR'), 'dois')
self.assertEqual(num2words(3, lang='pt_BR'), 'três')
self.assertEqual(num2words(4, lang='pt_BR'), 'quatro')
self.assertEqual(num2words(5, lang='pt_BR'), 'cinco')
self.assertEqual(num2words(6, lang='pt_BR'), 'seis')
self.assertEqual(num2words(7, lang='pt_BR'), 'sete')
self.assertEqual(num2words(8, lang='pt_BR'), 'oito')
self.assertEqual(num2words(9, lang='pt_BR'), 'nove')
self.assertEqual(num2words(10, lang='pt_BR'), 'dez')
self.assertEqual(num2words(11, lang='pt_BR'), 'onze')
self.assertEqual(num2words(12, lang='pt_BR'), 'doze')
self.assertEqual(num2words(13, lang='pt_BR'), 'treze')
self.assertEqual(num2words(14, lang='pt_BR'), 'catorze')
self.assertEqual(num2words(15, lang='pt_BR'), 'quinze')
self.assertEqual(num2words(16, lang='pt_BR'), 'dezesseis')
self.assertEqual(num2words(17, lang='pt_BR'), 'dezessete')
self.assertEqual(num2words(18, lang='pt_BR'), 'dezoito')
self.assertEqual(num2words(19, lang='pt_BR'), 'dezenove')
self.assertEqual(num2words(20, lang='pt_BR'), 'vinte')
self.assertEqual(num2words(21, lang='pt_BR'), 'vinte e um')
self.assertEqual(num2words(22, lang='pt_BR'), 'vinte e dois')
self.assertEqual(num2words(35, lang='pt_BR'), 'trinta e cinco')
self.assertEqual(num2words(99, lang='pt_BR'), 'noventa e nove')
self.assertEqual(num2words(100, lang='pt_BR'), 'cem')
self.assertEqual(num2words(101, lang='pt_BR'), 'cento e um')
self.assertEqual(num2words(128, lang='pt_BR'), 'cento e vinte e oito')
self.assertEqual(num2words(713, lang='pt_BR'), 'setecentos e treze')
self.assertEqual(num2words(1000, lang='pt_BR'), 'mil')
self.assertEqual(num2words(1001, lang='pt_BR'), 'mil e um')
self.assertEqual(num2words(1111, lang='pt_BR'), 'mil, cento e onze')
self.assertEqual(
num2words(2114, lang='pt_BR'), 'dois mil, cento e catorze'
)
self.assertEqual(
num2words(73421, lang='pt_BR'),
'setenta e três mil, quatrocentos e vinte e um'
)
self.assertEqual(num2words(100000, lang='pt_BR'), 'cem mil')
self.assertEqual(
num2words(250050, lang='pt_BR'),
'duzentos e cinquenta mil e cinquenta'
)
self.assertEqual(
num2words(6000000, lang='pt_BR'), 'seis milhões'
)
self.assertEqual(
num2words(19000000000, lang='pt_BR'), 'dezenove bilhões'
)
self.assertEqual(
num2words(145000000002, lang='pt_BR'),
'cento e quarenta e cinco bilhões e dois'
)
def test_cardinal_integer_negative(self):
self.assertEqual(num2words(-1, lang='pt_BR'), 'menos um')
self.assertEqual(
num2words(-256, lang='pt_BR'), 'menos duzentos e cinquenta e seis'
)
self.assertEqual(num2words(-1000, lang='pt_BR'), 'menos mil')
self.assertEqual(num2words(-1000000, lang='pt_BR'), 'menos um milhão')
self.assertEqual(
num2words(-1234567, lang='pt_BR'),
'menos um milhão, duzentos e trinta e quatro mil, quinhentos e '
'sessenta e sete'
)
def test_cardinal_float(self):
self.assertEqual(num2words(Decimal('1.00'), lang='pt_BR'), 'um')
self.assertEqual(num2words(
Decimal('1.01'), lang='pt_BR'), 'um vírgula zero um')
self.assertEqual(num2words(
Decimal('1.035'), lang='pt_BR'), 'um vírgula zero três cinco'
)
self.assertEqual(num2words(
Decimal('1.35'), lang='pt_BR'), 'um vírgula três cinco'
)
self.assertEqual(
num2words(Decimal('3.14159'), lang='pt_BR'),
'três vírgula um quatro um cinco nove'
)
self.assertEqual(
num2words(Decimal('101.22'), lang='pt_BR'),
'cento e um vírgula dois dois'
)
self.assertEqual(
num2words(Decimal('2345.75'), lang='pt_BR'),
'dois mil, trezentos e quarenta e cinco vírgula sete cinco')
def test_cardinal_float_negative(self):
self.assertEqual(
num2words(Decimal('-2.34'), lang='pt_BR'),
'menos dois vírgula três quatro'
)
self.assertEqual(
num2words(Decimal('-9.99'), lang='pt_BR'),
'menos nove vírgula nove nove'
)
self.assertEqual(
num2words(Decimal('-7.01'), lang='pt_BR'),
'menos sete vírgula zero um'
)
self.assertEqual(
num2words(Decimal('-222.22'), lang='pt_BR'),
'menos duzentos e vinte e dois vírgula dois dois'
)
def test_ordinal(self):
self.assertEqual(num2words(1, lang='pt_BR', ordinal=True), 'primeiro')
self.assertEqual(num2words(2, lang='pt_BR', ordinal=True), 'segundo')
self.assertEqual(num2words(3, lang='pt_BR', ordinal=True), 'terceiro')
self.assertEqual(num2words(4, lang='pt_BR', ordinal=True), 'quarto')
self.assertEqual(num2words(5, lang='pt_BR', ordinal=True), 'quinto')
self.assertEqual(num2words(6, lang='pt_BR', ordinal=True), 'sexto')
self.assertEqual(num2words(7, lang='pt_BR', ordinal=True), 'sétimo')
self.assertEqual(num2words(8, lang='pt_BR', ordinal=True), 'oitavo')
self.assertEqual(num2words(9, lang='pt_BR', ordinal=True), 'nono')
self.assertEqual(num2words(10, lang='pt_BR', ordinal=True), 'décimo')
self.assertEqual(
num2words(11, lang='pt_BR', ordinal=True), 'décimo primeiro'
)
self.assertEqual(
num2words(12, lang='pt_BR', ordinal=True), 'décimo segundo'
)
self.assertEqual(
num2words(13, lang='pt_BR', ordinal=True), 'décimo terceiro'
)
self.assertEqual(
num2words(14, lang='pt_BR', ordinal=True), 'décimo quarto'
)
self.assertEqual(
num2words(15, lang='pt_BR', ordinal=True), 'décimo quinto'
)
self.assertEqual(
num2words(16, lang='pt_BR', ordinal=True), 'décimo sexto'
)
self.assertEqual(
num2words(17, lang='pt_BR', ordinal=True), 'décimo sétimo'
)
self.assertEqual(
num2words(18, lang='pt_BR', ordinal=True), 'décimo oitavo'
)
self.assertEqual(
num2words(19, lang='pt_BR', ordinal=True), 'décimo nono'
)
self.assertEqual(
num2words(20, lang='pt_BR', ordinal=True), 'vigésimo'
)
self.assertEqual(
num2words(21, lang='pt_BR', ordinal=True), 'vigésimo primeiro'
)
self.assertEqual(
num2words(22, lang='pt_BR', ordinal=True), 'vigésimo segundo'
)
self.assertEqual(
num2words(35, lang='pt_BR', ordinal=True), 'trigésimo quinto'
)
self.assertEqual(
num2words(99, lang='pt_BR', ordinal=True), 'nonagésimo nono'
)
self.assertEqual(
num2words(100, lang='pt_BR', ordinal=True), 'centésimo'
)
self.assertEqual(
num2words(101, lang='pt_BR', ordinal=True), 'centésimo primeiro'
)
self.assertEqual(
num2words(128, lang='pt_BR', ordinal=True),
'centésimo vigésimo oitavo'
)
self.assertEqual(
num2words(713, lang='pt_BR', ordinal=True),
'septigentésimo décimo terceiro'
)
self.assertEqual(
num2words(1000, lang='pt_BR', ordinal=True), 'milésimo'
)
self.assertEqual(
num2words(1001, lang='pt_BR', ordinal=True), 'milésimo primeiro'
)
self.assertEqual(
num2words(1111, lang='pt_BR', ordinal=True),
'milésimo centésimo décimo primeiro'
)
self.assertEqual(
num2words(2114, lang='pt_BR', ordinal=True),
'segundo milésimo centésimo décimo quarto'
)
self.assertEqual(
num2words(73421, lang='pt_BR', ordinal=True),
'septuagésimo terceiro milésimo quadrigentésimo vigésimo primeiro'
)
self.assertEqual(
num2words(100000, lang='pt_BR', ordinal=True),
'centésimo milésimo'
)
self.assertEqual(
num2words(250050, lang='pt_BR', ordinal=True),
'ducentésimo quinquagésimo milésimo quinquagésimo'
)
self.assertEqual(
num2words(6000000, lang='pt_BR', ordinal=True), 'sexto milionésimo'
)
self.assertEqual(
num2words(19000000000, lang='pt_BR', ordinal=True),
'décimo nono bilionésimo'
)
self.assertEqual(
num2words(145000000002, lang='pt_BR', ordinal=True),
'centésimo quadragésimo quinto bilionésimo segundo'
)
def test_currency_integer(self):
self.assertEqual(self.n2w.to_currency(1), 'um real')
self.assertEqual(self.n2w.to_currency(2), 'dois reais')
self.assertEqual(self.n2w.to_currency(3), 'três reais')
self.assertEqual(self.n2w.to_currency(4), 'quatro reais')
self.assertEqual(self.n2w.to_currency(5), 'cinco reais')
self.assertEqual(self.n2w.to_currency(6), 'seis reais')
self.assertEqual(self.n2w.to_currency(7), 'sete reais')
self.assertEqual(self.n2w.to_currency(8), 'oito reais')
self.assertEqual(self.n2w.to_currency(9), 'nove reais')
self.assertEqual(self.n2w.to_currency(10), 'dez reais')
self.assertEqual(self.n2w.to_currency(11), 'onze reais')
self.assertEqual(self.n2w.to_currency(12), 'doze reais')
self.assertEqual(self.n2w.to_currency(13), 'treze reais')
self.assertEqual(self.n2w.to_currency(14), 'catorze reais')
self.assertEqual(self.n2w.to_currency(15), 'quinze reais')
self.assertEqual(self.n2w.to_currency(16), 'dezesseis reais')
self.assertEqual(self.n2w.to_currency(17), 'dezessete reais')
self.assertEqual(self.n2w.to_currency(18), 'dezoito reais')
self.assertEqual(self.n2w.to_currency(19), 'dezenove reais')
self.assertEqual(self.n2w.to_currency(20), 'vinte reais')
self.assertEqual(self.n2w.to_currency(21), 'vinte e um reais')
self.assertEqual(self.n2w.to_currency(22), 'vinte e dois reais')
self.assertEqual(self.n2w.to_currency(35), 'trinta e cinco reais')
self.assertEqual(self.n2w.to_currency(99), 'noventa e nove reais')
self.assertEqual(self.n2w.to_currency(100), 'cem reais')
self.assertEqual(self.n2w.to_currency(101), 'cento e um reais')
self.assertEqual(
self.n2w.to_currency(128), 'cento e vinte e oito reais'
)
self.assertEqual(self.n2w.to_currency(713), 'setecentos e treze reais')
self.assertEqual(self.n2w.to_currency(1000), 'mil reais')
self.assertEqual(self.n2w.to_currency(1001), 'mil e um reais')
self.assertEqual(self.n2w.to_currency(1111), 'mil, cento e onze reais')
self.assertEqual(
self.n2w.to_currency(2114), 'dois mil, cento e catorze reais'
)
self.assertEqual(
self.n2w.to_currency(73421),
'setenta e três mil, quatrocentos e vinte e um reais'
)
self.assertEqual(self.n2w.to_currency(100000), 'cem mil reais')
self.assertEqual(
self.n2w.to_currency(250050),
'duzentos e cinquenta mil e cinquenta reais'
)
self.assertEqual(
self.n2w.to_currency(6000000), 'seis milhões de reais'
)
self.assertEqual(
self.n2w.to_currency(19000000000), 'dezenove bilhões de reais'
)
self.assertEqual(
self.n2w.to_currency(145000000002),
'cento e quarenta e cinco bilhões e dois reais'
)
def test_currency_integer_negative(self):
self.assertEqual(self.n2w.to_currency(-1), 'menos um real')
self.assertEqual(
self.n2w.to_currency(-256),
'menos duzentos e cinquenta e seis reais'
)
self.assertEqual(self.n2w.to_currency(-1000), 'menos mil reais')
self.assertEqual(
self.n2w.to_currency(-1000000), 'menos um milhão de reais'
)
self.assertEqual(
self.n2w.to_currency(-1234567),
'menos um milhão, duzentos e trinta e quatro mil, quinhentos e '
'sessenta e sete reais'
)
def test_currency_float(self):
self.assertEqual(self.n2w.to_currency(Decimal('1.00')), 'um real')
self.assertEqual(
self.n2w.to_currency(Decimal('1.01')), 'um real e um centavo'
)
self.assertEqual(
self.n2w.to_currency(Decimal('1.03')), 'um real e três centavos'
)
self.assertEqual(
self.n2w.to_currency(Decimal('1.35')),
'um real e trinta e cinco centavos'
)
self.assertEqual(
self.n2w.to_currency(Decimal('3.14')),
'três reais e catorze centavos'
)
self.assertEqual(
self.n2w.to_currency(Decimal('101.22')),
'cento e um reais e vinte e dois centavos'
)
self.assertEqual(
self.n2w.to_currency(Decimal('2345.75')),
'dois mil, trezentos e quarenta e cinco reais e setenta e cinco '
'centavos'
)
def test_currency_float_negative(self):
self.assertEqual(
self.n2w.to_currency(Decimal('-2.34')),
'menos dois reais e trinta e quatro centavos'
)
self.assertEqual(
self.n2w.to_currency(Decimal('-9.99')),
'menos nove reais e noventa e nove centavos'
)
self.assertEqual(
self.n2w.to_currency(Decimal('-7.01')),
'menos sete reais e um centavo'
)
self.assertEqual(
self.n2w.to_currency(Decimal('-222.22')),
'menos duzentos e vinte e dois reais e vinte e dois centavos'
)
def test_year(self):
self.assertEqual(self.n2w.to_year(1001), 'mil e um')
self.assertEqual(
self.n2w.to_year(1789), 'mil, setecentos e oitenta e nove'
)
self.assertEqual(
self.n2w.to_year(1942), 'mil, novecentos e quarenta e dois'
)
self.assertEqual(
self.n2w.to_year(1984), 'mil, novecentos e oitenta e quatro'
)
self.assertEqual(self.n2w.to_year(2000), 'dois mil')
self.assertEqual(self.n2w.to_year(2001), 'dois mil e um')
self.assertEqual(self.n2w.to_year(2016), 'dois mil e dezesseis')
def test_year_negative(self):
self.assertEqual(self.n2w.to_year(-30), 'trinta antes de Cristo')
self.assertEqual(
self.n2w.to_year(-744),
'setecentos e quarenta e quatro antes de Cristo'
)
self.assertEqual(self.n2w.to_year(-10000), 'dez mil antes de Cristo')

173
tests/test_ro.py Normal file
View File

@ -0,0 +1,173 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from unittest import TestCase
from num2words import num2words
class Num2WordsROTest(TestCase):
def test_ordinal(self):
self.assertEqual(
num2words(1, lang='ro', to='ordinal'),
'primul'
)
self.assertEqual(
num2words(22, lang='ro', to='ordinal'),
u'al douăzeci și doilea'
)
self.assertEqual(
num2words(21, lang='ro', to='ordinal'),
u'al douăzeci și unulea'
)
self.assertEqual(
num2words(12, lang='ro', to='ordinal'),
u'al doisprezecelea'
)
self.assertEqual(
num2words(130, lang='ro', to='ordinal'),
u'al o sută treizecilea'
)
self.assertEqual(
num2words(1003, lang='ro', to='ordinal'),
u'al o mie treilea'
)
def test_ordinal_num(self):
self.assertEqual(
num2words(1, lang='ro', to='ordinal_num'),
'1-ul'
)
self.assertEqual(
num2words(10, lang='ro', to='ordinal_num'),
'al 10-lea'
)
self.assertEqual(num2words(
21, lang='ro', to='ordinal_num'),
'al 21-lea'
)
self.assertEqual(
num2words(102, lang='ro', to='ordinal_num'),
'al 102-lea'
)
self.assertEqual(
num2words(73, lang='ro', to='ordinal_num'),
'al 73-lea'
)
def test_cardinal_for_float_number(self):
self.assertEqual(
num2words(12.5, lang='ro'),
u'doisprezece virgulă cinci'
)
self.assertEqual(
num2words(12.51, lang='ro'),
u'doisprezece virgulă cinci unu'
)
self.assertEqual(
num2words(12.53, lang='ro'),
u'doisprezece virgulă cinci trei'
)
self.assertEqual(
num2words(12.59, lang='ro'),
u'doisprezece virgulă cinci nouă'
)
def test_big_numbers(self):
self.assertEqual(
num2words(1000000, lang="ro"),
u"un milion"
)
self.assertEqual(
num2words(1000000000, lang="ro"),
u"un miliard"
)
self.assertEqual(
num2words(33000000, lang="ro"),
u"treizeci și trei milioane"
)
self.assertEqual(
num2words(247000000000, lang="ro"),
u"două sute patruzeci și șapte miliarde"
)
def test_overflow(self):
with self.assertRaises(OverflowError):
num2words("100000000000000000000000000000000000000000000000000000"
"000000000000000000000000000000000000000000000000000000"
"000000000000000000000000000000000000000000000000000000"
"000000000000000000000000000000000000000000000000000000"
"000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000")
def test_to_currency(self):
self.assertEqual(
num2words(38.4, lang='ro', to='currency'),
u'treizeci și opt lei și patruzeci bani'
)
self.assertEqual(
num2words(1.01, lang='ro', to='currency'),
u'un leu și un ban'
)
self.assertEqual(
num2words(4778.00, lang='ro', to='currency'),
u'patru mii șapte sute șaptezeci și opt lei')
self.assertEqual(
num2words(4778.32, lang='ro', to='currency'),
u'patru mii șapte sute șaptezeci și opt lei'
u' și treizeci și doi bani')
def test_to_year(self):
self.assertEqual(num2words(1989, lang='ro', to='year'),
u'o mie nouă sute optzeci și nouă')
self.assertEqual(num2words(1984, lang='ro', to='year'),
u'o mie nouă sute optzeci și patru')
self.assertEqual(num2words(2018, lang='ro', to='year'),
u'două mii optsprezece')
self.assertEqual(num2words(1066, lang='ro', to='year'),
u'o mie șaizeci și șase')
self.assertEqual(num2words(5000, lang='ro', to='year'),
u'cinci mii')
self.assertEqual(num2words(2001, lang='ro', to='year'),
u'două mii unu')
self.assertEqual(num2words(905, lang='ro', to='year'),
u'nouă sute cinci')
self.assertEqual(num2words(6600, lang='ro', to='year'),
u'șase mii șase sute')
self.assertEqual(num2words(1600, lang='ro', to='year'),
u'o mie șase sute')
self.assertEqual(num2words(700, lang='ro', to='year'),
u'șapte sute')
self.assertEqual(num2words(50, lang='ro', to='year'),
u'cincizeci')
self.assertEqual(num2words(0, lang='ro', to='year'),
u'zero')
self.assertEqual(num2words(10, lang='ro', to='year'),
u'zece')
# suffixes
self.assertEqual(num2words(-44, lang='ro', to='year'),
u'patruzeci și patru î.Hr.')
self.assertEqual(num2words(-44, lang='ro', to='year',
suffix=u'î.e.n.'), u'patruzeci și patru î.e.n.')
self.assertEqual(num2words(1, lang='ro', to='year', suffix='d.Hr.'),
u'unu d.Hr.')
self.assertEqual(num2words(-66000000, lang='ro', to='year'),
u'șaizeci și șase milioane î.Hr.')

213
tests/test_ru.py Normal file
View File

@ -0,0 +1,213 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
class Num2WordsRUTest(TestCase):
def test_cardinal(self):
self.assertEqual(num2words(100, lang='ru'), "сто")
self.assertEqual(num2words(101, lang='ru'), "сто один")
self.assertEqual(num2words(110, lang='ru'), "сто десять")
self.assertEqual(num2words(115, lang='ru'), "сто пятнадцать")
self.assertEqual(num2words(123, lang='ru'), "сто двадцать три")
self.assertEqual(num2words(1000, lang='ru'), "одна тысяча")
self.assertEqual(num2words(1001, lang='ru'), "одна тысяча один")
self.assertEqual(num2words(2012, lang='ru'), "две тысячи двенадцать")
self.assertEqual(
num2words(12519.85, lang='ru'),
"двенадцать тысяч пятьсот девятнадцать запятая восемьдесят пять")
self.assertEqual(
num2words(1234567890, lang='ru'),
"один миллиард двести тридцать четыре миллиона пятьсот "
"шестьдесят семь тысяч восемьсот девяносто")
self.assertEqual(
num2words(215461407892039002157189883901676, lang='ru'),
"двести пятнадцать нониллионов четыреста шестьдесят один "
"октиллион четыреста семь септиллионов восемьсот девяносто "
"два секстиллиона тридцать девять квинтиллионов два квадриллиона "
"сто пятьдесят семь триллионов сто восемьдесят девять миллиардов "
"восемьсот восемьдесят три миллиона девятьсот одна тысяча "
"шестьсот семьдесят шесть")
self.assertEqual(
num2words(719094234693663034822824384220291, lang='ru'),
"семьсот девятнадцать нониллионов девяносто четыре октиллиона "
"двести тридцать четыре септиллиона шестьсот девяносто три "
"секстиллиона шестьсот шестьдесят три квинтиллиона тридцать "
"четыре квадриллиона восемьсот двадцать два триллиона восемьсот "
"двадцать четыре миллиарда триста восемьдесят четыре миллиона "
"двести двадцать тысяч двести девяносто один")
self.assertEqual(num2words(5, lang='ru'), "пять")
self.assertEqual(num2words(15, lang='ru'), "пятнадцать")
self.assertEqual(num2words(154, lang='ru'), "сто пятьдесят четыре")
self.assertEqual(
num2words(1135, lang='ru'), "одна тысяча сто тридцать пять"
)
self.assertEqual(
num2words(418531, lang='ru'),
"четыреста восемнадцать тысяч пятьсот тридцать один"
)
self.assertEqual(
num2words(1000139, lang='ru'), "один миллион сто тридцать девять"
)
self.assertEqual(num2words(-1, lang='ru'), "минус один")
self.assertEqual(num2words(-15, lang='ru'), "минус пятнадцать")
self.assertEqual(num2words(-100, lang='ru'), "минус сто")
def test_floating_point(self):
self.assertEqual(num2words(5.2, lang='ru'), "пять запятая два")
self.assertEqual(
num2words(561.42, lang='ru'),
"пятьсот шестьдесят один запятая сорок два"
)
def test_to_ordinal(self):
self.assertEqual(
num2words(1, lang='ru', to='ordinal'),
'первый'
)
self.assertEqual(
num2words(5, lang='ru', to='ordinal'),
'пятый'
)
self.assertEqual(
num2words(10, lang='ru', to='ordinal'),
'десятый'
)
self.assertEqual(
num2words(13, lang='ru', to='ordinal'),
'тринадцатый'
)
self.assertEqual(
num2words(20, lang='ru', to='ordinal'),
'двадцатый'
)
self.assertEqual(
num2words(23, lang='ru', to='ordinal'),
'двадцать третий'
)
self.assertEqual(
num2words(40, lang='ru', to='ordinal'),
'сороковой'
)
self.assertEqual(
num2words(70, lang='ru', to='ordinal'),
'семидесятый'
)
self.assertEqual(
num2words(100, lang='ru', to='ordinal'),
'сотый'
)
self.assertEqual(
num2words(136, lang='ru', to='ordinal'),
'сто тридцать шестой'
)
self.assertEqual(
num2words(500, lang='ru', to='ordinal'),
'пятисотый'
)
self.assertEqual(
num2words(1000, lang='ru', to='ordinal'),
'тысячный'
)
self.assertEqual(
num2words(1001, lang='ru', to='ordinal'),
'тысяча первый'
)
self.assertEqual(
num2words(2000, lang='ru', to='ordinal'),
'двух тысячный'
)
self.assertEqual(
num2words(10000, lang='ru', to='ordinal'),
'десяти тысячный'
)
self.assertEqual(
num2words(1000000, lang='ru', to='ordinal'),
'миллионный'
)
self.assertEqual(
num2words(1000000000, lang='ru', to='ordinal'),
'миллиардный'
)
def test_to_currency(self):
self.assertEqual(
num2words(1.0, lang='ru', to='currency', currency='EUR'),
'один евро, ноль центов'
)
self.assertEqual(
num2words(1.0, lang='ru', to='currency', currency='RUB'),
'один рубль, ноль копеек'
)
self.assertEqual(
num2words(1234.56, lang='ru', to='currency', currency='EUR'),
'одна тысяча двести тридцать четыре евро, пятьдесят шесть центов'
)
self.assertEqual(
num2words(1234.56, lang='ru', to='currency', currency='RUB'),
'одна тысяча двести тридцать четыре рубля, пятьдесят шесть копеек'
)
self.assertEqual(
num2words(10111, lang='ru', to='currency', currency='EUR',
seperator=' и'),
'сто один евро и одиннадцать центов'
)
self.assertEqual(
num2words(10121, lang='ru', to='currency', currency='RUB',
seperator=' и'),
'сто один рубль и двадцать одна копейка'
)
self.assertEqual(
num2words(10122, lang='ru', to='currency', currency='RUB',
seperator=' и'),
'сто один рубль и двадцать две копейки'
)
self.assertEqual(
num2words(10121, lang='ru', to='currency', currency='EUR',
seperator=' и'),
'сто один евро и двадцать один цент'
)
self.assertEqual(
num2words(-1251985, lang='ru', to='currency', currency='EUR',
cents=False),
'минус двенадцать тысяч пятьсот девятнадцать евро, 85 центов'
)
self.assertEqual(
num2words('38.4', lang='ru', to='currency', seperator=' и',
cents=False, currency='EUR'),
"тридцать восемь евро и 40 центов"
)
self.assertEqual(
num2words('1230.56', lang='ru', to='currency', currency='USD'),
'одна тысяча двести тридцать долларов, пятьдесят шесть центов'
)
self.assertEqual(
num2words('1231.56', lang='ru', to='currency', currency='USD'),
'одна тысяча двести тридцать один доллар, пятьдесят шесть центов'
)
self.assertEqual(
num2words('1234.56', lang='ru', to='currency', currency='USD'),
'одна тысяча двести тридцать четыре доллара, пятьдесят шесть '
'центов'
)

65
tests/test_sl.py Normal file
View File

@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
class Num2WordsDETest(TestCase):
def test_ordinal_less_than_twenty(self):
self.assertEqual(num2words(2, ordinal=True, lang='sl'), "drugi")
self.assertEqual(num2words(4, ordinal=True, lang='sl'), "četrti")
self.assertEqual(num2words(7, ordinal=True, lang='sl'), "sedmi")
self.assertEqual(num2words(8, ordinal=True, lang='sl'), "osmi")
self.assertEqual(num2words(12, ordinal=True, lang='sl'), "dvanajsti")
self.assertEqual(num2words(17, ordinal=True, lang='sl'), "sedemnajsti")
def test_ordinal_more_than_twenty(self):
self.assertEqual(
num2words(81, ordinal=True, lang='sl'), "enainosemdeseti"
)
def test_ordinal_at_crucial_number(self):
self.assertEqual(num2words(100, ordinal=True, lang='sl'), "stoti")
self.assertEqual(num2words(1000, ordinal=True, lang='sl'), "tisoči")
self.assertEqual(
num2words(4000, ordinal=True, lang='sl'), "štiritisoči"
)
self.assertEqual(
num2words(2000000, ordinal=True, lang='sl'), "dvemiljonti"
)
self.assertEqual(
num2words(5000000000, ordinal=True, lang='sl'), "petmiljardti"
)
def test_cardinal_at_some_numbers(self):
self.assertEqual(num2words(2, lang='sl'), "dve")
self.assertEqual(num2words(4000, lang='sl'), "štiri tisoč")
self.assertEqual(num2words(2000000, lang='sl'), "dva miljona")
self.assertEqual(num2words(4000000000, lang='sl'), "štiri miljarde")
def test_cardinal_for_decimal_number(self):
self.assertEqual(num2words(3.48, lang='sl'), "tri celih štiri osem")
def test_ordinal_for_negative_numbers(self):
self.assertRaises(TypeError, num2words, -12, ordinal=True, lang='sl')
def test_ordinal_for_floating_numbers(self):
self.assertRaises(TypeError, num2words, 2.453, ordinal=True, lang='sl')

243
tests/test_sr.py Normal file
View File

@ -0,0 +1,243 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
class Num2WordsSRTest(TestCase):
def test_cardinal(self):
self.assertEqual("sto", num2words(100, lang='sr'))
self.assertEqual("sto jedan", num2words(101, lang='sr'))
self.assertEqual("sto deset", num2words(110, lang='sr'))
self.assertEqual("sto petnaest", num2words(115, lang='sr'))
self.assertEqual(
"sto dvadeset tri", num2words(123, lang='sr')
)
self.assertEqual(
"jedna hiljada", num2words(1000, lang='sr')
)
self.assertEqual(
"jedna hiljada jedan", num2words(1001, lang='sr')
)
self.assertEqual(
"dve hiljade dvanaest", num2words(2012, lang='sr')
)
self.assertEqual(
"dvanaest hiljada petsto devetnaest zapeta osamdeset pet",
num2words(12519.85, lang='sr')
)
self.assertEqual(
"jedan bilion dvesta trideset četiri miliona petsto "
"šezdeset sedam hiljada osamsto devedeset",
num2words(1234567890, lang='sr')
)
self.assertEqual(
"dvesta petnaest noniliona četristo šezdeset jedan "
"oktilion četristo sedam septiliona osamsto devedeset "
"dva sekstiliona trideset devet kvintiliona dva kvadriliona "
"sto pedeset sedam triliona sto osamdeset devet biliona "
"osamsto osamdeset tri miliona devetsto jedna hiljada "
"šesto sedamdeset šest",
num2words(215461407892039002157189883901676, lang='sr')
)
self.assertEqual(
"sedamsto devetnaest noniliona devedeset četiri oktiliona "
"dvesta trideset četiri septiliona šesto devedeset tri "
"sekstiliona šesto šezdeset tri kvintiliona trideset "
"četiri kvadriliona osamsto dvadeset dva triliona osamsto "
"dvadeset četiri biliona trista osamdeset četiri miliona "
"dvesta dvadeset hiljada dvesta devedeset jedan",
num2words(719094234693663034822824384220291, lang='sr')
)
self.assertEqual("pet", num2words(5, lang='sr'))
self.assertEqual("petnaest", num2words(15, lang='sr'))
self.assertEqual("sto pedeset četiri", num2words(154, lang='sr'))
self.assertEqual(
"jedna hiljada sto trideset pet",
num2words(1135, lang='sr')
)
self.assertEqual(
"četristo osamnaest hiljada petsto trideset jedan",
num2words(418531, lang='sr'),
)
self.assertEqual(
"jedan milion sto trideset devet",
num2words(1000139, lang='sr')
)
def test_floating_point(self):
self.assertEqual("pet zapeta dva", num2words(5.2, lang='sr'))
self.assertEqual(
"petsto šezdeset jedan zapeta četrdeset dva",
num2words(561.42, lang='sr')
)
def test_to_ordinal(self):
# @TODO: implement to_ordinal
with self.assertRaises(NotImplementedError):
num2words(1, lang='sr', to='ordinal')
def test_to_currency(self):
self.assertEqual(
'jedan evro, nula centi',
num2words(1.0, lang='sr', to='currency', currency='EUR')
)
self.assertEqual(
'dva evra, nula centi',
num2words(2.0, lang='sr', to='currency', currency='EUR')
)
self.assertEqual(
'pet evra, nula centi',
num2words(5.0, lang='sr', to='currency', currency='EUR')
)
self.assertEqual(
'dva evra, jedan cent',
num2words(2.01, lang='sr', to='currency', currency='EUR')
)
self.assertEqual(
'dva evra, dva centa',
num2words(2.02, lang='sr', to='currency', currency='EUR')
)
self.assertEqual(
'dva evra, pet centi',
num2words(2.05, lang='sr', to='currency', currency='EUR')
)
self.assertEqual(
'dve rublje, nula kopejki',
num2words(2.0, lang='sr', to='currency', currency='RUB')
)
self.assertEqual(
'dve rublje, jedna kopejka',
num2words(2.01, lang='sr', to='currency', currency='RUB')
)
self.assertEqual(
'dve rublje, dve kopejke',
num2words(2.02, lang='sr', to='currency', currency='RUB')
)
self.assertEqual(
'dve rublje, pet kopejki',
num2words(2.05, lang='sr', to='currency', currency='RUB')
)
self.assertEqual(
'jedan dinar, nula para',
num2words(1.0, lang='sr', to='currency', currency='RSD')
)
self.assertEqual(
'dva dinara, dve pare',
num2words(2.02, lang='sr', to='currency', currency='RSD')
)
self.assertEqual(
'pet dinara, pet para',
num2words(5.05, lang='sr', to='currency', currency='RSD')
)
self.assertEqual(
'jedanaest dinara, jedanaest para',
num2words(11.11, lang='sr', to='currency', currency='RSD')
)
self.assertEqual(
'dvadeset jedan dinar, dvadeset jedna para',
num2words(21.21, lang='sr', to='currency', currency='RSD')
)
self.assertEqual(
'dvadeset jedan evro, dvadeset jedan cent',
num2words(21.21, lang='sr', to='currency', currency='EUR')
)
self.assertEqual(
'dvadeset jedna rublja, dvadeset jedna kopejka',
num2words(21.21, lang='sr', to='currency', currency='RUB')
)
self.assertEqual(
'jedna hiljada dvesta trideset četiri evra, '
'pedeset šest centi',
num2words(
1234.56, lang='sr', to='currency', currency='EUR'
)
)
self.assertEqual(
'jedna hiljada dvesta trideset četiri rublje, '
'pedeset šest kopejki',
num2words(
1234.56, lang='sr', to='currency', currency='RUB'
)
)
self.assertEqual(
'sto jedan evro i jedanaest centi',
num2words(
10111,
lang='sr',
to='currency',
currency='EUR',
seperator=' i'
)
)
self.assertEqual(
'sto jedna rublja i dvadeset jedna kopejka',
num2words(
10121,
lang='sr',
to='currency',
currency='RUB',
seperator=' i'
)
)
self.assertEqual(
'sto jedna rublja i dvadeset dve kopejke',
num2words(10122, lang='sr', to='currency', currency='RUB',
seperator=' i')
)
self.assertEqual(
'sto jedan evro i dvadeset jedan cent',
num2words(10121, lang='sr', to='currency', currency='EUR',
seperator=' i'),
)
self.assertEqual(
'minus dvanaest hiljada petsto devetnaest evra, 85 centi',
num2words(
-1251985,
lang='sr',
to='currency',
currency='EUR',
cents=False
)
)
self.assertEqual(
"trideset osam evra i 40 centi",
num2words('38.4', lang='sr', to='currency', seperator=' i',
cents=False, currency='EUR'),
)

208
tests/test_th.py Normal file
View File

@ -0,0 +1,208 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
from num2words.lang_TH import Num2Word_TH
class TestNumWord(TestCase):
def test_0(self):
self.assertEqual(num2words(0, lang='th'), "ศูนย์")
def test_end_with_1(self):
self.assertEqual(num2words(21, lang='th'), "ยี่สิบเอ็ด")
self.assertEqual(num2words(11, lang='th'), "สิบเอ็ด")
self.assertEqual(num2words(101, lang='th'), "หนึ่งร้อยเอ็ด")
self.assertEqual(num2words(1201, lang='th'), "หนึ่งพันสองร้อยเอ็ด")
def test_start_20(self):
self.assertEqual(num2words(22, lang='th'), "ยี่สิบสอง")
self.assertEqual(num2words(27, lang='th'), "ยี่สิบเจ็ด")
def test_start_10(self):
self.assertEqual(num2words(10, lang='th'), "สิบ")
self.assertEqual(num2words(18, lang='th'), "สิบแปด")
def test_1_to_9(self):
self.assertEqual(num2words(1, lang='th'), "หนึ่ง")
self.assertEqual(num2words(5, lang='th'), "ห้า")
self.assertEqual(num2words(9, lang='th'), "เก้า")
def test_31_to_99(self):
self.assertEqual(num2words(31, lang='th'), "สามสิบเอ็ด")
self.assertEqual(num2words(48, lang='th'), "สี่สิบแปด")
self.assertEqual(num2words(76, lang='th'), "เจ็ดสิบหก")
def test_100_to_999(self):
self.assertEqual(num2words(100, lang='th'), "หนึ่งร้อย")
self.assertEqual(num2words(123, lang='th'), "หนึ่งร้อยยี่สิบสาม")
self.assertEqual(num2words(456, lang='th'), "สี่ร้อยห้าสิบหก")
self.assertEqual(num2words(721, lang='th'), "เจ็ดร้อยยี่สิบเอ็ด")
def test_1000_to_9999(self):
self.assertEqual(num2words(1000, lang='th'), "หนึ่งพัน")
self.assertEqual(
num2words(2175, lang='th'), "สองพันหนึ่งร้อยเจ็ดสิบห้า"
)
self.assertEqual(num2words(4582, lang='th'), "สี่พันห้าร้อยแปดสิบสอง")
self.assertEqual(num2words(9346, lang='th'), "เก้าพันสามร้อยสี่สิบหก")
def test_10000_to_99999(self):
self.assertEqual(
num2words(11111, lang='th'), "หนึ่งหมื่นหนึ่งพันหนึ่งร้อยสิบเอ็ด"
)
self.assertEqual(
num2words(22222, lang='th'), "สองหมื่นสองพันสองร้อยยี่สิบสอง"
)
self.assertEqual(
num2words(84573, lang='th'), "แปดหมื่นสี่พันห้าร้อยเจ็ดสิบสาม"
)
def test_100000_to_999999(self):
self.assertEqual(
num2words(153247, lang='th'),
"หนึ่งแสนห้าหมื่นสามพันสองร้อยสี่สิบเจ็ด"
)
self.assertEqual(
num2words(562442, lang='th'),
"ห้าแสนหกหมื่นสองพันสี่ร้อยสี่สิบสอง"
)
self.assertEqual(
num2words(999999, lang='th'),
"เก้าแสนเก้าหมื่นเก้าพันเก้าร้อยเก้าสิบเก้า"
)
def test_more_than_million(self):
self.assertEqual(
num2words(1000000, lang='th'),
"หนึ่งล้าน"
)
self.assertEqual(
num2words(1000001, lang='th'),
"หนึ่งล้านเอ็ด"
)
self.assertEqual(
num2words(42478941, lang='th'),
"สี่สิบสองล้านสี่แสนเจ็ดหมื่นแปดพันเก้าร้อยสี่สิบเอ็ด"
)
self.assertEqual(
num2words(712696969, lang='th'),
"เจ็ดร้อยสิบสองล้านหกแสนเก้าหมื่นหกพันเก้าร้อยหกสิบเก้า"
)
self.assertEqual(
num2words(1000000000000000001, lang='th'),
"หนึ่งล้านล้านล้านเอ็ด"
)
def test_decimal(self):
self.assertEqual(
num2words(0.0, lang='th'), "ศูนย์"
)
self.assertEqual(
num2words(0.0038, lang='th'), "ศูนย์จุดศูนย์ศูนย์สามแปด"
)
self.assertEqual(
num2words(0.01, lang='th'), "ศูนย์จุดศูนย์หนึ่ง"
)
self.assertEqual(
num2words(1.123, lang='th'), "หนึ่งจุดหนึ่งสองสาม"
)
self.assertEqual(
num2words(35.37, lang='th'), "สามสิบห้าจุดสามเจ็ด"
)
self.assertEqual(
num2words(1000000.01, lang='th'), "หนึ่งล้านจุดศูนย์หนึ่ง"
)
def test_currency(self):
self.assertEqual(
num2words(100, lang='th', to='currency', currency='THB'),
"หนึ่งร้อยบาทถ้วน"
)
self.assertEqual(
num2words(100, lang='th', to='currency', currency='USD'),
"หนึ่งร้อยดอลลาร์"
)
self.assertEqual(
num2words(100, lang='th', to='currency', currency='EUR'),
"หนึ่งร้อยยูโร"
)
def test_currency_decimal(self):
self.assertEqual(
num2words(0.00, lang='th', to='currency'), "ศูนย์บาทถ้วน"
)
self.assertEqual(
num2words(0.05, lang='th', to='currency'), "ห้าสตางค์"
)
self.assertEqual(
num2words(0.50, lang='th', to='currency'), "ห้าสิบสตางค์"
)
self.assertEqual(
num2words(0.99, lang='th', to='currency'), "เก้าสิบเก้าสตางค์"
)
self.assertEqual(
num2words(100.00, lang='th', to='currency'), "หนึ่งร้อยบาทถ้วน"
)
self.assertEqual(
num2words(100.23, lang='th', to='currency', currency='USD'),
"หนึ่งร้อยดอลลาร์ยี่สิบสามเซนต์"
)
self.assertEqual(
num2words(100.24, lang='th', to='currency', currency='EUR'),
"หนึ่งร้อยยูโรยี่สิบสี่เซนต์"
)
def test_negative(self):
self.assertEqual(num2words(-10, lang='th'), "ติดลบสิบ")
self.assertEqual(num2words(-10.50, lang='th'), "ติดลบสิบจุดห้า")
self.assertEqual(
num2words(-100.00, lang='th', to='currency'),
"ติดลบหนึ่งร้อยบาทถ้วน"
)
def test_round_2_decimal(self):
n2wTH = Num2Word_TH()
self.assertEqual(n2wTH.round_2_decimal(0.004), ('0.00', False))
self.assertEqual(n2wTH.round_2_decimal(0.005), ('0.01', False))
self.assertEqual(n2wTH.round_2_decimal(0.006), ('0.01', False))
self.assertEqual(n2wTH.round_2_decimal(0.0005),
('0.00', False))
self.assertEqual(n2wTH.round_2_decimal(0.984), ('0.98', False))
self.assertEqual(n2wTH.round_2_decimal(0.989), ('0.99', False))
self.assertEqual(n2wTH.round_2_decimal(0.994), ('0.99', False))
self.assertEqual(n2wTH.round_2_decimal(0.999), ('1.00', False))
self.assertEqual(n2wTH.round_2_decimal(-0.994), ('0.99', True))
self.assertEqual(n2wTH.round_2_decimal(-0.999), ('1.00', True))
# self.assertEqual(n2wTH.round_2_decimal(0.985), ('0.99', False))
# Expect 0.99 get 0.98
# self.assertEqual(n2wTH.round_2_decimal(0.995), ('1.00', False))
# Expect 1.00 get 0.99
def test_split_six(self):
n2wTH = Num2Word_TH()
self.assertEqual(n2wTH.split_six(str(123456789)),
['987654', '321'])
self.assertEqual(n2wTH.split_six(str(12345)),
['54321'])
self.assertEqual(n2wTH.split_six(str(1234567)),
['765432', '1'])

193
tests/test_tr.py Normal file
View File

@ -0,0 +1,193 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from unittest import TestCase
from num2words import num2words
class Num2WordsTRTest(TestCase):
def test_tr(self):
# ref https://github.com/savoirfairelinux/num2words/issues/8
self.assertEqual(num2words(1, True, "tr"), u"birinci")
self.assertEqual(num2words(2, True, "tr"), u"ikinci")
self.assertEqual(num2words(9, True, "tr"), u"dokuzuncu")
self.assertEqual(num2words(10, True, "tr"), u"onuncu")
self.assertEqual(num2words(11, True, "tr"), u"onbirinci")
self.assertEqual(num2words(44, True, "tr"), u"kırkdördüncü")
self.assertEqual(num2words(100, True, "tr"), u"yüzüncü")
self.assertEqual(num2words(101, True, "tr"), u"yüzbirinci")
self.assertEqual(num2words(103, True, "tr"), u"yüzüçüncü")
self.assertEqual(num2words(110, True, "tr"), u"yüzonuncu")
self.assertEqual(num2words(111, True, "tr"), u"yüzonbirinci")
self.assertEqual(num2words(1000, True, "tr"), u"bininci")
self.assertEqual(num2words(1001, True, "tr"), u"binbirinci")
self.assertEqual(num2words(1010, True, "tr"), u"binonuncu")
self.assertEqual(num2words(1011, True, "tr"), u"binonbirinci")
self.assertEqual(num2words(1100, True, "tr"), u"binyüzüncü")
self.assertEqual(num2words(1110, True, "tr"), u"binyüzonuncu")
self.assertEqual(
num2words(2341, True, "tr"), u"ikibinüçyüzkırkbirinci"
)
self.assertEqual(num2words(10000, True, "tr"), u"onbininci")
self.assertEqual(num2words(10010, True, "tr"), u"onbinonuncu")
self.assertEqual(num2words(10100, True, "tr"), u"onbinyüzüncü")
self.assertEqual(num2words(10110, True, "tr"), u"onbinyüzonuncu")
self.assertEqual(num2words(11000, True, "tr"), u"onbirbininci")
self.assertEqual(num2words(35000, True, "tr"), u"otuzbeşbininci")
self.assertEqual(
num2words(116331, True, "tr"), u"yüzonaltıbinüçyüzotuzbirinci"
)
self.assertEqual(
num2words(116330, True, "tr"), u"yüzonaltıbinüçyüzotuzuncu"
)
self.assertEqual(num2words(100000, True, "tr"), u"yüzbininci")
self.assertEqual(num2words(501000, True, "tr"), u"beşyüzbirbininci")
self.assertEqual(
num2words(1000111, True, "tr"), u"birmilyonyüzonbirinci"
)
self.assertEqual(
num2words(111000111, True, "tr"), u"yüzonbirmilyonyüzonbirinci"
)
self.assertEqual(
num2words(111001111, True, "tr"), u"yüzonbirmilyonbinyüzonbirinci"
)
self.assertEqual(
num2words(111111111, True, "tr"),
u"yüzonbirmilyonyüzonbirbinyüzonbirinci"
)
self.assertEqual(num2words(100001000, True, "tr"), u"yüzmilyonbininci")
self.assertEqual(
num2words(100001001, True, "tr"), u"yüzmilyonbinbirinci"
)
self.assertEqual(
num2words(100010000, True, "tr"), u"yüzmilyononbininci"
)
self.assertEqual(
num2words(100010001, True, "tr"), u"yüzmilyononbinbirinci"
)
self.assertEqual(
num2words(100011000, True, "tr"), u"yüzmilyononbirbininci"
)
self.assertEqual(
num2words(100011001, True, "tr"), u"yüzmilyononbirbinbirinci"
)
self.assertEqual(
num2words(101011001, True, "tr"), u"yüzbirmilyononbirbinbirinci"
)
self.assertEqual(
num2words(101011010, True, "tr"), u"yüzbirmilyononbirbinonuncu"
)
self.assertEqual(
num2words(1101011010, True, "tr"),
u"birmilyaryüzbirmilyononbirbinonuncu"
)
self.assertEqual(
num2words(101101011010, True, "tr"),
u"yüzbirmilyaryüzbirmilyononbirbinonuncu"
)
self.assertEqual(
num2words(1000000000001, True, "tr"), u"birtrilyonbirinci"
)
self.assertEqual(num2words(1, False, "tr"), u"bir")
self.assertEqual(num2words(2, False, "tr"), u"iki")
self.assertEqual(num2words(9, False, "tr"), u"dokuz")
self.assertEqual(num2words(10, False, "tr"), u"on")
self.assertEqual(num2words(11, False, "tr"), u"onbir")
self.assertEqual(num2words(44, False, "tr"), u"kırkdört")
self.assertEqual(num2words(100, False, "tr"), u"yüz")
self.assertEqual(num2words(101, False, "tr"), u"yüzbir")
self.assertEqual(num2words(103, False, "tr"), u"yüzüç")
self.assertEqual(num2words(110, False, "tr"), u"yüzon")
self.assertEqual(num2words(111, False, "tr"), u"yüzonbir")
self.assertEqual(num2words(1000, False, "tr"), u"bin")
self.assertEqual(num2words(1001, False, "tr"), u"binbir")
self.assertEqual(num2words(1010, False, "tr"), u"binon")
self.assertEqual(num2words(1011, False, "tr"), u"binonbir")
self.assertEqual(num2words(1100, False, "tr"), u"binyüz")
self.assertEqual(num2words(1110, False, "tr"), u"binyüzon")
self.assertEqual(num2words(2341, False, "tr"), u"ikibinüçyüzkırkbir")
self.assertEqual(num2words(10000, False, "tr"), u"onbin")
self.assertEqual(num2words(10010, False, "tr"), u"onbinon")
self.assertEqual(num2words(10100, False, "tr"), u"onbinyüz")
self.assertEqual(num2words(10110, False, "tr"), u"onbinyüzon")
self.assertEqual(num2words(11000, False, "tr"), u"onbirbin")
self.assertEqual(num2words(35000, False, "tr"), u"otuzbeşbin")
self.assertEqual(
num2words(116331, False, "tr"), u"yüzonaltıbinüçyüzotuzbir"
)
self.assertEqual(
num2words(116330, False, "tr"), u"yüzonaltıbinüçyüzotuz"
)
self.assertEqual(num2words(500000, False, "tr"), u"beşyüzbin")
self.assertEqual(num2words(501000, False, "tr"), u"beşyüzbirbin")
self.assertEqual(num2words(1000111, False, "tr"), u"birmilyonyüzonbir")
self.assertEqual(
num2words(111000111, False, "tr"), u"yüzonbirmilyonyüzonbir"
)
self.assertEqual(
num2words(111001111, False, "tr"), u"yüzonbirmilyonbinyüzonbir"
)
self.assertEqual(
num2words(111111111, False, "tr"),
u"yüzonbirmilyonyüzonbirbinyüzonbir"
)
self.assertEqual(num2words(100001000, False, "tr"), u"yüzmilyonbin")
self.assertEqual(num2words(100001001, False, "tr"), u"yüzmilyonbinbir")
self.assertEqual(num2words(100010000, False, "tr"), u"yüzmilyononbin")
self.assertEqual(
num2words(100010001, False, "tr"), u"yüzmilyononbinbir"
)
self.assertEqual(
num2words(100011000, False, "tr"), u"yüzmilyononbirbin"
)
self.assertEqual(
num2words(100011001, False, "tr"), u"yüzmilyononbirbinbir"
)
self.assertEqual(
num2words(101011001, False, "tr"), u"yüzbirmilyononbirbinbir"
)
self.assertEqual(
num2words(101011010, False, "tr"), u"yüzbirmilyononbirbinon"
)
self.assertEqual(
num2words(1101011010, False, "tr"),
u"birmilyaryüzbirmilyononbirbinon"
)
self.assertEqual(
num2words(101101011010, False, "tr"),
u"yüzbirmilyaryüzbirmilyononbirbinon"
)
self.assertEqual(
num2words(1000000000001, False, "tr"), u"birtrilyonbir"
)
self.assertEqual(num2words(0.01, False, "tr"), u"sıfırvirgülbir")
self.assertEqual(num2words(0.1, False, "tr"), u"sıfırvirgülon")
self.assertEqual(num2words(0.21, False, "tr"), u"sıfırvirgülyirmibir")
self.assertEqual(num2words(1.01, False, "tr"), u"birvirgülbir")
self.assertEqual(num2words(1.1, False, "tr"), u"birvirgülon")
self.assertEqual(num2words(1.21, False, "tr"), u"birvirgülyirmibir")
self.assertEqual(
num2words(101101011010.02, False, "tr"),
u"yüzbirmilyaryüzbirmilyononbirbinonvirgüliki"
)
self.assertEqual(
num2words(101101011010.2, False, "tr"),
u"yüzbirmilyaryüzbirmilyononbirbinonvirgülyirmi"
)

135
tests/test_uk.py Normal file
View File

@ -0,0 +1,135 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
class Num2WordsUKTest(TestCase):
def test_to_cardinal(self):
self.maxDiff = None
self.assertEqual(num2words(100, lang='uk'), 'сто')
# self.assertEqual(num2words(101, lang='uk'), 'сто один')
self.assertEqual(num2words(110, lang='uk'), 'сто десять')
self.assertEqual(num2words(115, lang='uk'), "сто п'ятнадцять")
self.assertEqual(num2words(123, lang='uk'), 'сто двадцять три')
self.assertEqual(num2words(1000, lang='uk'), 'одна тисяча')
# self.assertEqual(num2words(1001, lang='uk'), 'одна тисяча один')
self.assertEqual(num2words(2012, lang='uk'), 'двi тисячi дванадцять')
self.assertEqual(
num2words(12519.85, lang='uk'),
"дванадцять тисяч п'ятсот дев'ятнадцять кома вiсiмдесят п'ять")
# self.assertEqual(
# num2words(1234567890, lang='uk'),
# "мiльярд двiстi тридцать чотири мiльйона п'ятсот шiстдесят сiмь "
# "тисяч вiссот дев'яносто")
# self.assertEqual(
# num2words(215461407892039002157189883901676, lang='uk'),
# "двiстi п'ятнадцять нонiльйонiв чотириста шiстдесят один "
# "октильйон чотириста ссептильйонiв вiссот дев'яносто "
# "два секстильйони тридцять дев'ять квiнтильйонiв два "
# "квадрильйони сто п'ятдесят сiм трильйонiв сто вiсiмдесят "
# "дев'ять мiльярдiв вiссот вiсiмдесят три мiльйона "
# "дев'ятсот одна тисяча шiстсот "
# "сiмдесят шiсть")
# self.assertEqual(
# num2words(719094234693663034822824384220291, lang='uk'),
# "ссот дев'ятнадцять нонiльйонiв дев'яносто чотири октильйони "
# "двiстi тридцять чотири септильйони шiстсот дев'яносто три "
# "секстильйони шiстсот шiстдесят три квiнтильйони тридцять "
# "чотири квадрильйони вiссот двадцять два трильйони вiссот "
# "двадцять чотири мiльярди триста вiсiмдесят чотири мiльйона "
# "двiстi двадцять тисяч двiстi дев'яносто один")
def test_and_join_199(self):
self.assertEqual(num2words(187, lang='uk'), "сто вiсiмдесят с")
def test_cardinal_for_float_number(self):
self.assertEqual(
num2words(12.40, lang='uk'), "дванадцять кома чотири"
)
self.assertEqual(
num2words(17.31, lang='uk'), "сiмнадцять кома тридцять одна"
)
self.assertEqual(
num2words(14.13, lang='uk'), "чотирнадцять кома тринадцять"
)
self.assertEqual(
num2words(12.31, lang='uk'), "дванадцять кома тридцять одна"
)
def test_to_ordinal(self):
# @TODO: implement to_ordinal
with self.assertRaises(NotImplementedError):
num2words(1, lang='uk', to='ordinal')
def test_to_currency(self):
# self.assertEqual(
# num2words(1.0, lang='uk', to='currency', currency='EUR'),
# "один євро, нуль центiв"
# )
self.assertEqual(
num2words(1.0, lang='uk', to='currency', currency='UAH'),
"одна гривня, нуль копiйок"
)
self.assertEqual(
num2words(1234.56, lang='uk', to='currency', currency='EUR'),
"одна тисяча двiстi тридцять чотири євро, п'ятдесят шiсть центiв"
)
self.assertEqual(
num2words(1234.56, lang='uk', to='currency', currency='UAH'),
"одна тисяча двiстi тридцять чотири гривнi, п'ятдесят шiсть "
"копiйок"
)
# self.assertEqual(
# num2words(10111, lang='uk', to='currency', currency='EUR',
# seperator=u' та'),
# "сто один євро та одинадцять центiв"
# )
self.assertEqual(
num2words(10121, lang='uk', to='currency', currency='UAH',
seperator=u' та'),
"сто одна гривня та двадцять одна копiйка"
)
self.assertEqual(
num2words(10121, lang='uk', to='currency', currency='UAH',
seperator=u' та'),
"сто одна гривня та двадцять одна копiйка"
)
self.assertEqual(
num2words(10122, lang='uk', to='currency', currency='UAH',
seperator=u' та'),
"сто одна гривня та двадцять двi копiйки"
)
# self.assertEqual(
# num2words(10121, lang='uk', to='currency', currency='EUR',
# seperator=u' та'),
# "сто один євро та двадцять один цент"
# )
self.assertEqual(
num2words(-1251985, lang='uk', to='currency', currency='EUR',
cents=False),
"мiнус дванадцять тисяч п'ятсот дев'ятнадцять євро, 85 центiв"
)
self.assertEqual(
num2words('38.4', lang='uk', to='currency', seperator=' и',
cents=False, currency='EUR'),
"тридцять вiсiм євро и 40 центiв"
)

41
tests/test_utils.py Normal file
View File

@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from unittest import TestCase
from num2words.utils import splitbyx
class TestUtils(TestCase):
def test_splitbyx(self):
self.assertEqual(list(splitbyx(str(12), 3)), [12])
self.assertEqual(list(splitbyx(str(1234), 3)), [1, 234])
self.assertEqual(list(splitbyx(str(12345678900), 3)),
[12, 345, 678, 900]
)
self.assertEqual(list(splitbyx(str(1000000), 6)), [1, 0])
self.assertEqual(list(splitbyx(str(12), 3, format_int=False)), ['12'])
self.assertEqual(list(splitbyx(str(1234), 3, format_int=False)),
['1', '234']
)
self.assertEqual(list(splitbyx(str(12345678900), 3, format_int=False)),
['12', '345', '678', '900']
)
self.assertEqual(list(splitbyx(str(1000000), 6, format_int=False)),
['1', '000000']
)

139
tests/test_vi.py Normal file
View File

@ -0,0 +1,139 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA
from __future__ import unicode_literals
from unittest import TestCase
from num2words import num2words
class Num2WordsVITest(TestCase):
def test_0(self):
self.assertEqual(num2words(0, lang="vi"), "không")
def test_1_to_10(self):
self.assertEqual(num2words(1, lang="vi"), "một")
self.assertEqual(num2words(2, lang="vi"), "hai")
self.assertEqual(num2words(7, lang="vi"), "bảy")
self.assertEqual(num2words(10, lang="vi"), "mười")
def test_11_to_19(self):
self.assertEqual(num2words(11, lang="vi"), "mười một")
self.assertEqual(num2words(13, lang="vi"), "mười ba")
self.assertEqual(num2words(14, lang="vi"), "mười bốn")
self.assertEqual(num2words(15, lang="vi"), "mười lăm")
self.assertEqual(num2words(16, lang="vi"), "mười sáu")
self.assertEqual(num2words(19, lang="vi"), "mười chín")
def test_20_to_99(self):
self.assertEqual(num2words(20, lang="vi"), "hai mươi")
self.assertEqual(num2words(23, lang="vi"), "hai mươi ba")
self.assertEqual(num2words(28, lang="vi"), "hai mươi tám")
self.assertEqual(num2words(31, lang="vi"), "ba mươi mốt")
self.assertEqual(num2words(40, lang="vi"), "bốn mươi")
self.assertEqual(num2words(66, lang="vi"), "sáu mươi sáu")
self.assertEqual(num2words(92, lang="vi"), "chín mươi hai")
def test_100_to_999(self):
self.assertEqual(num2words(100, lang="vi"), "một trăm")
self.assertEqual(num2words(150, lang="vi"), "một trăm năm mươi")
self.assertEqual(
num2words(196, lang="vi"), "một trăm chín mươi sáu"
)
self.assertEqual(num2words(200, lang="vi"), "hai trăm")
self.assertEqual(num2words(210, lang="vi"), "hai trăm mười")
def test_1000_to_9999(self):
self.assertEqual(num2words(1000, lang="vi"), "một nghìn")
self.assertEqual(num2words(1500, lang="vi"), "một nghìn năm trăm")
self.assertEqual(
num2words(7378, lang="vi"), "bảy nghìn ba trăm bảy mươi tám"
)
self.assertEqual(num2words(2000, lang="vi"), "hai nghìn")
self.assertEqual(num2words(2100, lang="vi"), "hai nghìn một trăm")
self.assertEqual(
num2words(6870, lang="vi"), "sáu nghìn tám trăm bảy mươi"
)
self.assertEqual(num2words(10000, lang="vi"), "mười nghìn")
self.assertEqual(num2words(100000, lang="vi"), "một trăm nghìn")
self.assertEqual(
num2words(523456, lang="vi"),
"năm trăm hai mươi ba nghìn bốn trăm năm mươi sáu"
)
def test_big(self):
self.assertEqual(num2words(1000000, lang="vi"), "một triệu")
self.assertEqual(
num2words(1200000, lang="vi"), "một triệu hai trăm nghìn"
)
self.assertEqual(num2words(3000000, lang="vi"), "ba triệu")
self.assertEqual(
num2words(3800000, lang="vi"), "ba triệu tám trăm nghìn"
)
self.assertEqual(num2words(1000000000, lang="vi"), "một tỷ")
self.assertEqual(num2words(2000000000, lang="vi"), "hai tỷ")
self.assertEqual(
num2words(2000001000, lang="vi"), "hai tỷ một nghìn"
)
self.assertEqual(
num2words(1234567890, lang="vi"),
"một tỷ hai trăm ba mươi bốn triệu năm trăm sáu mươi bảy nghìn "
"tám trăm chín mươi"
)
def test_decimal_number(self):
self.assertEqual(
num2words(1000.11, lang="vi"), "một nghìn phẩy mười một"
)
self.assertEqual(
num2words(1000.21, lang="vi"), "một nghìn phẩy hai mươi mốt"
)
def test_special_number(self):
"""
Some number will have some specail rule
"""
self.assertEqual(num2words(21, lang="vi"), "hai mươi mốt")
self.assertEqual(num2words(25, lang="vi"), "hai mươi lăm")
# >100
self.assertEqual(num2words(101, lang="vi"), "một trăm lẻ một")
self.assertEqual(num2words(105, lang="vi"), "một trăm lẻ năm")
self.assertEqual(num2words(701, lang="vi"), "bảy trăm lẻ một")
self.assertEqual(num2words(705, lang="vi"), "bảy trăm lẻ năm")
# >1000
self.assertEqual(num2words(1001, lang="vi"), "một nghìn lẻ một")
self.assertEqual(num2words(1005, lang="vi"), "một nghìn lẻ năm")
self.assertEqual(
num2words(98765, lang="vi"),
"chín mươi tám nghìn bảy trăm sáu mươi lăm"
)
# > 1000000
self.assertEqual(num2words(3000005, lang="vi"), "ba triệu lẻ năm")
self.assertEqual(num2words(1000007, lang="vi"), "một triệu lẻ bảy")
# > 1000000000
self.assertEqual(
num2words(1000000017, lang="vi"), "một tỷ lẻ mười bảy"
)
self.assertEqual(
num2words(1000101017, lang="vi"),
"một tỷ một trăm lẻ một nghìn lẻ mười bảy"
)

28
tox.ini Normal file
View File

@ -0,0 +1,28 @@
[tox]
envlist = flake8,isort,py27,py34,py35,py36,py37
[testenv]
passenv = TRAVIS TRAVIS_*
deps =
coverage
delegator.py
commands =
coverage run -m unittest discover
coverage report --fail-under=75 --omit=.tox/*,tests/*,/usr/*
coverage report --fail-under=100 --include=tests/* --skip-covered
[testenv:flake8]
changedir = {toxinidir}
deps =
flake8
flake8-copyright
commands =
flake8
[testenv:isort]
changedir = {toxinidir}
deps =
isort
delegator.py
commands =
isort --check-only --recursive --diff num2words tests