2
0
mirror of https://github.com/tenrok/numeralize-ru.git synced 2026-06-08 17:22:36 +03:00
This commit is contained in:
anotherpit
2016-03-31 04:04:29 +03:00
commit add510b5c8
8 changed files with 1679 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
# editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[package.json]
indent_size = 2
+103
View File
@@ -0,0 +1,103 @@
# Created by .ignore support plugin (hsz.mobi)
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Node template
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directory
# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
node_modules
### OSX template
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
+104
View File
@@ -0,0 +1,104 @@
# Created by .ignore support plugin (hsz.mobi)
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Node template
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directory
# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
node_modules
### OSX template
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
test
+9
View File
@@ -0,0 +1,9 @@
# The MIT License
Copyright © 2016 anotherpit <anotherpit@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+102
View File
@@ -0,0 +1,102 @@
# numeralize-ru
Написание числительных на русском языке с учётом пола и падежа.
# Установка
```
npm install --save numeralize-ru
```
# API
`numeralize(number, [gender, [kase, [animate]]])` — возвращает числительное, соответствующее числу
+ `number` — число, для которого надо записать числительное;
+ `gender` - пол:
+ `numeralize.GENDER_MASCULINE` - мужской (по умолчанию);
+ `numeralize.GENDER_FEMININE` - женский;
+ `numeralize.GENDER_NEUTER` - средний;
+ `kase` - падеж (`case` является ключевым словом, поэтому не может быть использован в качестве имени переменной):
+ `numeralize.CASE_NOMINATIVE` - именительный (по умолчанию);
+ `numeralize.CASE_GENITIVE` - родительный;
+ `numeralize.CASE_DATIVE` - дательный;
+ `numeralize.CASE_ACCUSATIVE` - винительный;
+ `numeralize.CASE_INSTRUMENTAL` - творительный;
+ `numeralize.CASE_PREPOSITIONAL` - предложный;
+ `animate` - являются ли перечисляемые предметы одушевлёнными (влияет на форму винительного падежа некоторых числительных)
```javascript
const numeralize = require('numeralize);
numeralize(5122981121);
// мужской род, 'пять миллиардов сто двадцать два миллиона девятьсот восемьдесят одна тысяча сто двадцать один'
numeralize(5122981121, numeralize.GENDER_FEMININE);
// женский род, 'пять миллиардов сто двадцать два миллиона девятьсот восемьдесят одна тысяча сто двадцать одна'
numeralize(5122981121, numeralize.GENDER_NEUTER);
// средний род, 'пять миллиардов сто двадцать два миллиона девятьсот восемьдесят одна тысяча сто двадцать одно'
numeralize(5122981121, numeralize.GENDER_MASCULINE, numeralize.CASE_NOMINATIVE);
// мужской род, именительный падеж, 'пять миллиардов сто двадцать два миллиона девятьсот восемьдесят одна тысяча сто двадцать один'
numeralize(5122981121, numeralize.GENDER_MASCULINE, numeralize.CASE_GENITIVE);
// мужской род, родительный падеж, 'пяти миллиардов ста двадцати двух миллионов девятисот восьмидесяти одной тысячи ста двадцати одного'
numeralize(5122981121, numeralize.GENDER_MASCULINE, numeralize.CASE_DATIVE);
// мужской род, дательный падеж, 'пяти миллиардам ста двадцати двум миллионам девятистам восьмидесяти одной тысяче ста двадцати одному'
numeralize(5122981121, numeralize.GENDER_MASCULINE, numeralize.CASE_ACCUSATIVE);
// мужской род, винительный падеж, 'пять миллиардов сто двадцать два миллиона девятьсот восемьдесят одну тысячу сто двадцать один'
numeralize(5122981121, numeralize.GENDER_MASCULINE, numeralize.CASE_ACCUSATIVE, true);
// мужской род, винительный падеж, одушевлённые предметы, 'пять миллиардов сто двадцать два миллиона девятьсот восемьдесят одну тысячу сто двадцать одного'
numeralize(5122981121, numeralize.GENDER_MASCULINE, numeralize.CASE_INSTRUMENTAL);
// мужской род, творительный падеж, 'пятью миллиардами ста двадцатью двумя миллионами девятьюстами восемьюдесятью одной тысячей ста двадцатью одним'
numeralize(5122981121, numeralize.GENDER_MASCULINE, numeralize.CASE_PREPOSITIONAL);
// мужской род, творительный падеж, 'пяти миллиардах ста двадцати двух миллионах девятистах восьмидесяти одной тысяче ста двадцати одном'
```
`numeralize.pluralize(number, one, two, five)` — выбирает нужную форму существительного в зависимости от количества
+ `number` количество
+ `one` — форма существительного для одного предмета, например, _рубль_;
+ `two` — форма существительного для двух предметов, например, _рубля_;
+ `five` — форма существительного для пяти предметов, например, _рублей_;
```javascript
const pluralize = require('numeralize).pluralize;
pluralize(0, 'рубль', 'рубля', 'рублей');
// 'рублей'
pluralize(1, 'рубль', 'рубля', 'рублей');
// 'рубль'
pluralize(2, 'рубль', 'рубля', 'рублей');
// 'рубля'
pluralize(5, 'рубль', 'рубля', 'рублей');
// 'рублей'
pluralize(11, 'рубль', 'рубля', 'рублей');
// 'рублей'
pluralize(21, 'рубль', 'рубля', 'рублей');
// 'рубль'
pluralize(21, 'рубль', 'рубля', 'рублей');
// 'рубля'
```
# Roadmap
+ Порядковые числительные (ordinal numerals): _первый_, _вторым_, _третьими_ и т.д.
+ Собирательные числительные (collective numerals): _трое_, _четверых_, _пятерыми_ и т.д.
+ Особые формы единственного и множественного числа: _одни сутки_, _два дня_, _пять суток_ и т.д.
# См.также
+ Подробно о склонении числительных в русском языке с примерами: http://numeralonline.ru/
+240
View File
@@ -0,0 +1,240 @@
;(function(root, factory) {
if (typeof define === 'function' && define.amd) {
define([], factory);
} else if (typeof exports === 'object') {
module.exports = factory();
} else {
root.numeralize = factory();
}
}(this, function() {
'use strict';
/**
* Numeralize number
* @param {number} number Integer
* @param {number} [gender=numeralize.GENDER_MASCULINE]
* @param {number} [kase=numeralize.CASE_NOMINATIVE]
* @param {boolean} [animate=false]
* @returns {string}
*/
function numeralize(number, gender, kase, animate) {
// Normalize params
number = Math.abs(parseInt(number, 10));
gender = gender || numeralize.GENDER_MASCULINE;
kase = kase || numeralize.CASE_NOMINATIVE;
animate = !!animate;
// Collect chunks
var result = [];
// Descend known powers of thousand
for (var l = LARGES.length, i = l; i >= 0; i--) {
var base = Math.pow(10, i * 3);
var current = Math.floor(number / base);
number = number % base;
if (current) {
var words = i ? LARGES[i] : null;
var numeral = small(current, words ? words[0] : gender, kase, words ? false : animate);
if (numeral) {
result.push(numeral);
if (words) {
var plural = pluralize.apply(null, [current].concat(words[kase + 1]));
result.push(plural);
}
}
}
}
// Zero
if (!result.length) {
return MINORS[0][kase];
}
// Return
return result.join(" ");
}
/**
* Numeralize small number (< 1000)
* @private
* @param {number} number Non-negative integer < 1000
* @param {number} gender
* @param {number} kase
* @param {boolean} animate
* @returns {string}
*/
function small(number, gender, kase, animate) {
// Zero
if (0 === number) { return ""; }
// Collect chunks
var result = [];
// Hundreds
var hundreds = Math.floor(number / 100);
if (HUNDREDS[hundreds]) {
result.push(HUNDREDS[hundreds][kase]);
}
// Tens
var tens = Math.floor(number % 100 / 10);
if (TENS[tens]) {
result.push(TENS[tens][kase]);
}
// Minors
var minors = number % 100;
if (minors >= MINORS.length) {
minors = number % 10;
}
if (minors) {
minors = MINORS[minors][kase];
if ("string" !== typeof minors) {
minors = minors[gender];
if ("string" !== typeof minors) {
minors = minors[animate ? 0 : 1];
}
}
result.push(minors);
}
// Return
return result.join(" ");
}
/**
* Pluralize noun according to count
* @param {number} count Number of items
* @param {string} one E.g. «рубль»
* @param {string} two E.g. «рубля»
* @param {string} five E.g. «рублей»
* @returns {string}
*/
function pluralize(count, one, two, five) {
count = Math.floor(Math.abs(count)) % 100;
if (count > 10 && count < 20) {
return five;
}
count = count % 10;
if (1 === count) { return one; }
if (count >= 2 && count <= 4) { return two; }
return five;
}
numeralize.GENDER_MASCULINE = 0;
numeralize.GENDER_FEMININE = 1;
numeralize.GENDER_NEUTER = 2;
numeralize.CASE_NOMINATIVE = 0;
numeralize.CASE_GENITIVE = 1;
numeralize.CASE_DATIVE = 2;
numeralize.CASE_ACCUSATIVE = 3;
numeralize.CASE_INSTRUMENTAL = 4;
numeralize.CASE_PREPOSITIONAL = 5;
numeralize.pluralize = pluralize;
var MINORS = [
['ноль', 'нуля', 'нулю', 'ноль', 'нулём', 'нуле'],
[
['один', 'одна', 'одно'],
['одного', 'одной', 'одного'],
['одному', 'одной', 'одному'],
[['одного', 'один'], 'одну', 'одно'],
['одним', 'одной', 'одним'],
['одном', 'одной', 'одном']
],
[
['два', 'две', 'два'],
'двух',
'двум',
[['двух', 'два'], ['двух', 'две'], 'два'],
'двумя',
'двух'
],
[
'три',
'трёх',
'трём',
[['трёх', 'три'], ['трёх', 'три'], 'три'],
'тремя',
'трёх'
],
[
'четыре',
'четырёх',
'четырём',
[['четырёх', 'четыре'], ['четырёх', 'четыре'], 'четыре'],
'четырьмя',
'четырёх'
],
['пять', 'пяти', 'пяти', 'пять', 'пятью', 'пяти'],
['шесть', 'шести', 'шести', 'шесть', 'шестью', 'шести'],
['семь', 'семи', 'семи', 'семь', 'семью', 'семи'],
['восемь', 'восьми', 'восьми', 'восемь', 'восемью', 'восьми'],
['девять', 'девяти', 'девяти', 'девять', 'девятью', 'девяти'],
['десять', 'десяти', 'десяти', 'десять', 'десятью', 'десяти']
].concat(
['один', 'две', 'три', 'четыр', 'пят', 'шест', 'сем', 'восем', 'девят'].map(function(prefix) {
return ['надцать', 'надцати', 'надцати', 'надцать', 'надцатью', 'надцати'].map(function(suffix) {
return prefix + suffix;
});
})
);
var TENS = [
false,
false,
['двадцать', 'двадцати', 'двадцати', 'двадцать', 'двадцатью', 'двадцати'],
['тридцать', 'тридцати', 'тридцати', 'тридцать', 'тридцатью', 'тридцати'],
['сорок', 'сорока', 'сорока', 'сорок', 'сорока', 'сорока'],
['пятьдесят', 'пятидесяти', 'пятидесяти', 'пятьдесят', 'пятьюдесятью', 'пятидесяти'],
['шестьдесят', 'шестидесяти', 'шестидесяти', 'шестьдесят', 'шестьюдесятью', 'шестидесяти'],
['семьдесят', 'семидесяти', 'семидесяти', 'семьдесят', 'семьюдесятью', 'семидесяти'],
['восемьдесят', 'восьмидесяти', 'восьмидесяти', 'восемьдесят', 'восемьюдесятью', 'восьмидесяти'],
['девяносто', 'девяноста', 'девяноста', 'девяносто', 'девяноста', 'девяноста']
];
var HUNDREDS = [
false,
['сто', 'ста', 'ста', 'сто', 'ста', 'ста'],
['двести', 'двухсот', 'двумстам', 'двести', 'двумястами', 'двухстах'],
['триста', 'трёхсот', 'трёмстам', 'триста', 'тремястами', 'трёхстах'],
['четыреста', 'четырёхсот', 'четырёмстам', 'четыреста', 'четырьмястами', 'четырёхстах'],
['пятьсот', 'пятисот', 'пятистам', 'пятьсот', 'пятьюстами', 'пятистах'],
['шестьсот', 'шестисот', 'шестистам', 'шестьсот', 'шестьюстами', 'шестистах'],
['семьсот', 'семисот', 'семистам', 'семьсот', 'семьюстами', 'семистах'],
['восемьсот', 'восьмисот', 'восьмистам', 'восемьсот', 'восемьюстами', 'восьмистах'],
['девятьсот', 'девятисот', 'девятистам', 'девятьсот', 'девятьюстами', 'девятистах']
];
var LARGES = [
false,
[
numeralize.GENDER_FEMININE,
['тысяча', 'тысячи', 'тысяч'],
['тысячи', 'тысяч', 'тысяч'],
['тысяче', 'тысячам', 'тысячам'],
['тысячу', 'тысячи', 'тысяч'],
['тысячей', 'тысячами', 'тысячами'],
['тысяче', 'тысячах', 'тысячах']
]
].concat(['миллион', 'миллиард', 'триллион'].map(function(base) {
return [numeralize.GENDER_MASCULINE]
.concat([
['', 'а', 'ов'],
['а', 'ов', 'ов'],
['у', 'ам', 'ам'],
['', 'а', 'ов'],
['ом', 'ами', 'ами'],
['е', 'ах', 'ах']
].map(function(kase) {
return kase.map(function(suffix) {
return base + suffix;
});
}));
}));
return numeralize;
}));
+30
View File
@@ -0,0 +1,30 @@
{
"name": "numeralize-ru",
"version": "1.0.0",
"description": "Russian numerals",
"main": "index.js",
"scripts": {
"test": "./node_modules/.bin/mocha",
"dev": "./node_modules/.bin/mocha --watch"
},
"keywords": [
"russian",
"language",
"number",
"numeral",
"cardinal",
"ordinal",
"collective",
"numeralize",
"ru"
],
"author": "anotherpit <anotherpit@gmail.com>",
"license": "MIT",
"devDependencies": {
"mocha": "^2.4.5"
},
"repository": {
"type": "git",
"url": "https://github.com/anotherpit/numeralize-ru.git"
}
}
+1078
View File
File diff suppressed because it is too large Load Diff