├── .npmignore ├── .gitignore ├── test ├── .eslintrc.json ├── pl.test.js ├── my.test.js ├── ur.test.js ├── ml.test.js ├── am.test.js ├── el.test.js ├── zh.test.js ├── hi.test.js ├── da.test.js ├── pa.test.js ├── nl.test.js ├── mr.test.js ├── ar.test.js ├── sk.test.js ├── pt.test.js ├── fi.test.js ├── bg.test.js ├── fr.test.js ├── ja.test.js ├── kk.test.js ├── ru.test.js ├── es.test.js ├── hy.test.js ├── en.test.js └── de.test.js ├── src ├── languages │ ├── ca.js │ ├── mr.js │ ├── ja.js │ ├── el.js │ ├── am.js │ ├── my.js │ ├── ar.js │ ├── hy.js │ ├── hi.js │ ├── or.js │ ├── pa.js │ ├── bn.js │ ├── gu.js │ ├── kn.js │ ├── te.js │ ├── ml.js │ ├── bg.js │ ├── ru.js │ ├── ta.js │ ├── index.js │ ├── fr.js │ ├── pt.js │ ├── pl.js │ ├── fi.js │ ├── en.js │ ├── de.js │ ├── es.js │ ├── sk.js │ ├── kk.js │ ├── da.js │ └── nl.js ├── index.js ├── fallbacks.json ├── base.js └── terminators.js ├── .eslintrc.json ├── bin └── segment.mjs ├── .github └── workflows │ ├── npm.yaml │ └── nodejs.yaml ├── rollup.config.js ├── LICENSE ├── package.json ├── README.md └── docs └── index.html /.npmignore: -------------------------------------------------------------------------------- 1 | .github 2 | test -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .vscode 4 | -------------------------------------------------------------------------------- /test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/languages/ca.js: -------------------------------------------------------------------------------- 1 | import Spanish from './es.js' 2 | 3 | export default class Catalan extends Spanish { 4 | } 5 | -------------------------------------------------------------------------------- /src/languages/mr.js: -------------------------------------------------------------------------------- 1 | import Hindi from './hi.js' 2 | 3 | export default class Marathi extends Hindi { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/languages/ja.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | 3 | const abbreviations = new Set([ 4 | // TOOD: Add abbreviations 5 | ]) 6 | 7 | export default class Japanese extends BaseLanguage { 8 | static abbreviations = abbreviations 9 | } 10 | -------------------------------------------------------------------------------- /src/languages/el.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | import GLOBAL_SENTENCE_TERMINATORS from './../terminators.js' 3 | 4 | export default class Greek extends BaseLanguage { 5 | static abbreviations = new Set() 6 | static sentenceBreakRegex = new RegExp( 7 | `[${GLOBAL_SENTENCE_TERMINATORS.concat([';']).join('')}]+`, 8 | 'g' 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /src/languages/am.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | import English from './en.js' 3 | 4 | const abbreviations = new Set([ 5 | ...English.abbreviations, 6 | 'ዓ', 7 | 'ም' 8 | ]) 9 | 10 | export default class Amharic extends BaseLanguage { 11 | static abbreviations = abbreviations 12 | continueInNextWord (textAfterBoundary) { 13 | return textAfterBoundary.match(/^\W*[0-9a-z]/) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/languages/my.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | import English from './en.js' 3 | import GLOBAL_SENTENCE_TERMINATORS from './../terminators.js' 4 | 5 | export default class Burmese extends BaseLanguage { 6 | static abbreviations = English.abbreviations 7 | // See https://en.wiktionary.org/wiki/၏ 8 | static sentenceBreakRegex = new RegExp( 9 | `[${GLOBAL_SENTENCE_TERMINATORS.concat(['၏']).join('')}]+`, 10 | 'g' 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /src/languages/ar.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | 3 | const abbreviations = new Set([ 4 | 'إلخ', 5 | 'ا. د', 6 | 'ا.د', 7 | 'ا.ش.ا', 8 | 'ا', 9 | 'ت.ب', 10 | 'ج.ب', 11 | 'ج.م.ع', 12 | 'جم', 13 | 'س.ت', 14 | 'سم', 15 | 'ص.ب.', 16 | 'ص.ب', 17 | 'كج.', 18 | 'كلم.', 19 | 'م.ب', 20 | 'م', 21 | 'ه' 22 | 23 | ]) 24 | 25 | export default class Arabic extends BaseLanguage { 26 | static abbreviations = abbreviations 27 | } 28 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "node": true 6 | }, 7 | "extends": ["standard"], 8 | "parser": "@babel/eslint-parser", 9 | "parserOptions": { 10 | "requireConfigFile": false, 11 | "ecmaVersion": "latest", 12 | "sourceType": "module", 13 | "babelOptions": { 14 | "plugins": [ 15 | "@babel/plugin-syntax-import-assertions" 16 | ] 17 | } 18 | }, 19 | "rules": {} 20 | } 21 | 22 | -------------------------------------------------------------------------------- /bin/segment.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | 'use strict' 4 | 5 | import segment from '../src/index.js' 6 | import fs from 'fs' 7 | 8 | const text = fs.readFileSync('/dev/stdin', 'utf8') 9 | if (text.trim() === '' || process.argv.length !== 3) { 10 | const script = process.argv[1] 11 | process.stderr.write( 12 | 'Usage: node ' + script + ' language < file\n' 13 | ) 14 | process.exit(1) 15 | } 16 | const language = process.argv[2] 17 | console.log(segment(language, text)) 18 | -------------------------------------------------------------------------------- /test/pl.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 'To słowo bałt. jestskrótem.': ['To słowo bałt. jestskrótem.'] 6 | } 7 | 8 | describe('Polish segment()', function () { 9 | for (const [text, expectedSentences] of Object.entries(tests)) { 10 | it(`correctly segments text: ${text}`, function () { 11 | const sentences = segment('pl', text) 12 | assert.deepEqual(sentences, expectedSentences) 13 | }) 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /test/my.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 'ခင္ဗ်ားနာမည္ဘယ္လိုေခၚလဲ။ င္ေနေကာင္းလား။': ['ခင္ဗ်ားနာမည္ဘယ္လိုေခၚလဲ။', 'င္ေနေကာင္းလား။'] 6 | } 7 | 8 | describe('Burmese segment()', function () { 9 | for (const [text, expectedSentences] of Object.entries(tests)) { 10 | it(`correctly segments text: ${text}`, function () { 11 | const sentences = segment('my', text) 12 | assert.deepEqual(sentences, expectedSentences) 13 | }) 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /src/languages/hy.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | import English from './en.js' 3 | import GLOBAL_SENTENCE_TERMINATORS from './../terminators.js' 4 | 5 | const hyTerminators = ['։', '՜', ':'].concat(GLOBAL_SENTENCE_TERMINATORS) 6 | hyTerminators.splice(hyTerminators.indexOf('.'), 1) 7 | const hyTerminatorsRegex = new RegExp(`[${hyTerminators.join('')}]+`, 'g') 8 | 9 | export default class Armenian extends BaseLanguage { 10 | static abbreviations = English.abbreviations 11 | static sentenceBreakRegex = hyTerminatorsRegex 12 | } 13 | -------------------------------------------------------------------------------- /test/ur.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 6 | 'کیا حال ہے؟ ميرا نام ___ ەے۔ میں حالا تاوان دےدوں؟': 7 | ['کیا حال ہے؟', 'ميرا نام ___ ەے۔', 'میں حالا تاوان دےدوں؟'] 8 | 9 | } 10 | 11 | describe('Urdu segment()', function () { 12 | for (const [text, expectedSentences] of Object.entries(tests)) { 13 | it(`correctly segments text: ${text}`, function () { 14 | const sentences = segment('ur', text) 15 | assert.deepEqual(sentences, expectedSentences) 16 | }) 17 | } 18 | }) 19 | -------------------------------------------------------------------------------- /.github/workflows/npm.yaml: -------------------------------------------------------------------------------- 1 | name: Publish Package to npmjs.org 2 | on: 3 | release: 4 | types: [published] 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v4 10 | # Setup .npmrc file to publish to npm 11 | - uses: actions/setup-node@v3 12 | with: 13 | node-version: '20.x' 14 | registry-url: 'https://registry.npmjs.org' 15 | - run: npm ci 16 | - run: npm run build 17 | - run: npm publish 18 | env: 19 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 20 | -------------------------------------------------------------------------------- /src/languages/hi.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | import English from './en.js' 3 | 4 | const abbreviations = new Set([ 5 | ...English.abbreviations, 6 | 'ए', 7 | 'बी', 8 | 'सी', 9 | 'डी', 10 | 'ई', 11 | 'एफ', 12 | 'जी', 13 | 'एच', 14 | 'आई', 15 | 'जे', 16 | 'के', 17 | 'एल', 18 | 'एम', 19 | 'एन', 20 | 'ओ', 21 | 'पी', 22 | 'क्यू', 23 | 'आर', 24 | 'एस', 25 | 'टी', 26 | 'यू', 27 | 'भी', 28 | 'डब्लू', 29 | 'एक्स', 30 | 'वाई', 31 | 'जेड' 32 | ]) 33 | 34 | export default class Hindi extends BaseLanguage { 35 | static abbreviations = abbreviations 36 | } 37 | -------------------------------------------------------------------------------- /src/languages/or.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | import English from './en.js' 3 | 4 | const abbreviations = new Set([ 5 | ...English.abbreviations, 6 | 'ଏ', 7 | 'ବି', 8 | 'ସି', 9 | 'ଡି', 10 | 'ଈ', 11 | 'ଏଫ', 12 | 'ଜି', 13 | 'ହ୍', 14 | 'ଆଇ', 15 | 'ଜେ', 16 | 'କେ', 17 | 'ଏଲ', 18 | 'ଏମ', 19 | 'ଏନ', 20 | 'ଓ', 21 | 'ପି', 22 | 'କ୍ୟୁ', 23 | 'ଆର', 24 | 'ଏସ', 25 | 'ଟି', 26 | 'ୟୁ', 27 | 'ଭି', 28 | 'ଡବଲ୍ୱ୍', 29 | 'ଏକ୍ସ', 30 | 'ଏବଂ', 31 | 'ଜେଡ' 32 | ]) 33 | 34 | export default class Odia extends BaseLanguage { 35 | static abbreviations = abbreviations 36 | } 37 | -------------------------------------------------------------------------------- /src/languages/pa.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | import English from './en.js' 3 | 4 | const abbreviations = new Set([ 5 | ...English.abbreviations, 6 | 'ਏ', 7 | 'ਬੀ', 8 | 'ਸੀ', 9 | 'ਡੀ', 10 | 'ਈ', 11 | 'ਐਫ', 12 | 'ਜੀ', 13 | 'ਐਚ', 14 | 'ਆਈ', 15 | 'ਜੇ', 16 | 'ਕੇ', 17 | 'ਐਲ', 18 | 'ਐਮ', 19 | 'ਐਨ', 20 | 'ਓ', 21 | 'ਪੀ', 22 | 'ਕਿਊ', 23 | 'ਆਰ', 24 | 'ਐਸ', 25 | 'ਟੀ', 26 | 'ਯੂ', 27 | 'ਵੀ', 28 | 'ਡਬਲਯੂ', 29 | 'ਐਕਸ', 30 | 'ਵਾਈ', 31 | 'ਜੇਡ' 32 | ]) 33 | 34 | export default class Punjabi extends BaseLanguage { 35 | static abbreviations = abbreviations 36 | } 37 | -------------------------------------------------------------------------------- /src/languages/bn.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | import English from './en.js' 3 | 4 | const abbreviations = new Set([ 5 | ...English.abbreviations, 6 | 'এ', 7 | 'বি', 8 | 'সি', 9 | 'ডি', 10 | 'ঈ', 11 | 'এফ', 12 | 'জি', 13 | 'এইচ', 14 | 'আই', 15 | 'জে', 16 | 'কে', 17 | 'এল', 18 | 'এম', 19 | 'এন', 20 | 'ও', 21 | 'পি', 22 | 'কিউ', 23 | 'আর', 24 | 'এস', 25 | 'টি', 26 | 'ইউ', 27 | 'ভি', 28 | 'ডাবলিউ', 29 | 'এক্স', 30 | 'ওয়াই', 31 | 'জেড' 32 | ]) 33 | 34 | export default class Bengali extends BaseLanguage { 35 | static abbreviations = abbreviations 36 | } 37 | -------------------------------------------------------------------------------- /src/languages/gu.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | import English from './en.js' 3 | 4 | const abbreviations = new Set([ 5 | ...English.abbreviations, 6 | 'એ', 7 | 'બી', 8 | 'સી', 9 | 'ડી', 10 | 'ઈ', 11 | 'એફ', 12 | 'જી', 13 | 'એચ', 14 | 'આઈ', 15 | 'જે', 16 | 'કે', 17 | 'એલ', 18 | 'એમ', 19 | 'એન', 20 | 'ઓ', 21 | 'પી', 22 | 'ક્યૂ', 23 | 'આર', 24 | 'એસ', 25 | 'ટી', 26 | 'યૂ', 27 | 'વી', 28 | 'ડબલ્યૂ', 29 | 'એક્સ', 30 | 'વાય', 31 | 'જેડ' 32 | ]) 33 | 34 | export default class Gujarati extends BaseLanguage { 35 | static abbreviations = abbreviations 36 | } 37 | -------------------------------------------------------------------------------- /src/languages/kn.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | import English from './en.js' 3 | 4 | const abbreviations = new Set([ 5 | ...English.abbreviations, 6 | 'ಎ', 7 | 'ಬಿ', 8 | 'ಸಿ', 9 | 'ಡಿ', 10 | 'ಈ', 11 | 'ಎಫ್', 12 | 'ಜಿ', 13 | 'ಹೆಚ್', 14 | 'ಐ', 15 | 'ಜೆ', 16 | 'ಕೆ', 17 | 'ಎಲ್', 18 | 'ಎಂ', 19 | 'ಎನ್', 20 | 'ಓ', 21 | 'ಪಿ', 22 | 'ಕ್ಯೂ', 23 | 'ಆರ್', 24 | 'ಎಸ್', 25 | 'ಟಿ', 26 | 'ಯೂ', 27 | 'ವಿ', 28 | 'ಡಬಲ್ಯೂ', 29 | 'ಎಕ್ಸ್', 30 | 'ವೈ', 31 | 'ಜೆಡ್' 32 | ]) 33 | 34 | export default class Kannada extends BaseLanguage { 35 | static abbreviations = abbreviations 36 | } 37 | -------------------------------------------------------------------------------- /src/languages/te.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | import English from './en.js' 3 | 4 | const abbreviations = new Set([ 5 | ...English.abbreviations, 6 | 'ఎ', 7 | 'బి', 8 | 'సి', 9 | 'డి', 10 | 'ఈ', 11 | 'ఎఫ్', 12 | 'జి', 13 | 'హెచ్', 14 | 'ఐ', 15 | 'జె', 16 | 'కె', 17 | 'ఎల్', 18 | 'ఎం', 19 | 'ఎన్', 20 | 'ఓ', 21 | 'పి', 22 | 'క్యూ', 23 | 'ఆర్', 24 | 'ఎస్', 25 | 'టి', 26 | 'యూ', 27 | 'వి', 28 | 'డబ్ల్యూ', 29 | 'ఎక్స్', 30 | 'వై', 31 | 'జెడ్' 32 | ]) 33 | 34 | export default class Telugu extends BaseLanguage { 35 | static abbreviations = abbreviations 36 | } 37 | -------------------------------------------------------------------------------- /test/ml.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 'ഇത് ഡോ. ശിവൻ. ഇദ്ദേഹമാണ് ഞാൻ പറഞ്ഞയാൾ': ['ഇത് ഡോ. ശിവൻ.', 'ഇദ്ദേഹമാണ് ഞാൻ പറഞ്ഞയാൾ'], 6 | 'ഇത് മി. കെ. പി. മോഹനൻ': ['ഇത് മി. കെ. പി. മോഹനൻ'], 7 | 'ഇത് പ്രൊ. കെ.പി. മോഹനൻ': ['ഇത് പ്രൊ. കെ.പി. മോഹനൻ'], 8 | 'ഇത് Dr. മോഹനൻ': ['ഇത് Dr. മോഹനൻ'] 9 | 10 | } 11 | 12 | describe('Malayalam segment()', function () { 13 | for (const [text, expectedSentences] of Object.entries(tests)) { 14 | it(`correctly segments text: ${text}`, function () { 15 | const sentences = segment('ml', text) 16 | assert.deepEqual(sentences, expectedSentences) 17 | }) 18 | } 19 | }) 20 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import pkg from './package.json' assert { type: 'json' } 2 | import json from '@rollup/plugin-json' 3 | import esbuild from 'rollup-plugin-esbuild' 4 | 5 | export default [ 6 | { 7 | input: 'src/index.js', 8 | output: [ 9 | { 10 | name: pkg.name, 11 | file: pkg.module, 12 | format: 'esm', 13 | sourcemap: true 14 | }, 15 | { 16 | name: pkg.name, 17 | file: pkg.main, 18 | format: 'umd', 19 | sourcemap: true 20 | } 21 | ], 22 | plugins: [ 23 | json(), 24 | esbuild({ 25 | sourceMap: true, 26 | minify: true 27 | }) 28 | 29 | ] 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import LANGUAGE_FALLBACKS from './fallbacks.json' assert { type: 'json' } 2 | 3 | import languages from './languages/index.js' 4 | 5 | function getLanguageClass (language) { 6 | if (language in languages) { 7 | return languages[language] 8 | } 9 | 10 | const fallbacks = LANGUAGE_FALLBACKS[language] || ['en'] 11 | for (const fallbackLanguage of fallbacks) { 12 | const cls = getLanguageClass(fallbackLanguage) 13 | if (cls) { 14 | return cls 15 | } 16 | } 17 | } 18 | 19 | export default function segment (language, text) { 20 | const className = getLanguageClass(language) 21 | // eslint-disable-next-line new-cap 22 | return new className().segment(text) 23 | } 24 | -------------------------------------------------------------------------------- /test/am.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 'እንደምን አለህ፧መልካም ቀን ይሁንልህ።እባክሽ ያልሽዉን ድገሚልኝ።': ['እንደምን አለህ፧', 'መልካም ቀን ይሁንልህ።', 'እባክሽ ያልሽዉን ድገሚልኝ።'], 6 | 'ቴዎድሮስ ጥር ፮ ቀን ፲፰፻፲፩ ዓ.ም. ሻርጌ በተባለ ቦታ ቋራ ውስጥ፣ ከጎንደር ከተማ በስተ ምዕራብ ተወለዱ።': [ 7 | 'ቴዎድሮስ ጥር ፮ ቀን ፲፰፻፲፩ ዓ.ም. ሻርጌ በተባለ ቦታ ቋራ ውስጥ፣ ከጎንደር ከተማ በስተ ምዕራብ ተወለዱ።' 8 | ] 9 | } 10 | 11 | describe('Amharic segment()', function () { 12 | for (const [text, expectedSentences] of Object.entries(tests)) { 13 | it(`correctly segments text: ${text}`, function () { 14 | const sentences = segment('am', text) 15 | assert.deepEqual(sentences, expectedSentences) 16 | }) 17 | } 18 | }) 19 | -------------------------------------------------------------------------------- /test/el.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 'Με συγχωρείτε· πού είναι οι τουαλέτες; Τις Κυριακές δε δούλευε κανένας. το κόστος του σπιτιού ήταν £260.950,00.': 6 | [ 7 | 'Με συγχωρείτε· πού είναι οι τουαλέτες;', 8 | 'Τις Κυριακές δε δούλευε κανένας.', 9 | 'το κόστος του σπιτιού ήταν £260.950,00.' 10 | ] 11 | } 12 | 13 | describe('Greek segment()', function () { 14 | for (const [text, expectedSentences] of Object.entries(tests)) { 15 | it(`correctly segments text: ${text}`, function () { 16 | const sentences = segment('el', text) 17 | assert.deepEqual(sentences, expectedSentences) 18 | }) 19 | } 20 | }) 21 | -------------------------------------------------------------------------------- /test/zh.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | '安永已聯繫周怡安親屬,協助辦理簽證相關事宜,周怡安家屬1月1日晚間搭乘東方航空班機抵達上海,他們步入入境大廳時神情落寞、不發一語。周怡安來自台中,去年剛從元智大學畢業,同年9月加入安永。': 6 | [ 7 | '安永已聯繫周怡安親屬,協助辦理簽證相關事宜,周怡安家屬1月1日晚間搭乘東方航空班機抵達上海,他們步入入境大廳時神情落寞、不發一語。', 8 | '周怡安來自台中,去年剛從元智大學畢業,同年9月加入安永。' 9 | ], 10 | 11 | '我们明天一起去看《摔跤吧!爸爸》好吗?好!': ['我们明天一起去看《摔跤吧!爸爸》好吗?', '好!'] 12 | } 13 | 14 | describe('Chinese segment()', function () { 15 | for (const [text, expectedSentences] of Object.entries(tests)) { 16 | it(`correctly segments text: ${text}`, function () { 17 | const sentences = segment('zh', text) 18 | assert.deepEqual(sentences, expectedSentences) 19 | }) 20 | } 21 | }) 22 | -------------------------------------------------------------------------------- /test/hi.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 'सच्चाई यह है कि इसे कोई नहीं जानता। हो सकता है यह फ़्रेन्को के खिलाफ़ कोई विद्रोह रहा हो, या फिर बेकाबू हो गया कोई आनंदोत्सव।': 6 | [ 7 | 'सच्चाई यह है कि इसे कोई नहीं जानता।', 8 | 'हो सकता है यह फ़्रेन्को के खिलाफ़ कोई विद्रोह रहा हो, या फिर बेकाबू हो गया कोई आनंदोत्सव।' 9 | ] 10 | } 11 | 12 | describe('Hindi segment()', function () { 13 | for (const [text, expectedSentences] of Object.entries(tests)) { 14 | it(`correctly segments text: ${text}`, function () { 15 | const sentences = segment('hi', text) 16 | assert.deepEqual(sentences, expectedSentences) 17 | }) 18 | } 19 | }) 20 | -------------------------------------------------------------------------------- /test/da.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 'Hej Verden. Mit navn er Jonas.': ['Hej Verden.', 'Mit navn er Jonas.'], 6 | 'Hvad er dit navn? Mit nav er Jonas.': ['Hvad er dit navn?', 'Mit nav er Jonas.'], 7 | 'De holdt Skt. Hans i byen.': ['De holdt Skt. Hans i byen.'], 8 | "St. Michael's Kirke er på 5. gade nær ved lyset.": 9 | ["St. Michael's Kirke er på 5. gade nær ved lyset."] 10 | } 11 | 12 | describe('Danish segment()', function () { 13 | for (const [text, expectedSentences] of Object.entries(tests)) { 14 | it(`correctly segments text: ${text}`, function () { 15 | const sentences = segment('da', text) 16 | assert.deepEqual(sentences, expectedSentences) 17 | }) 18 | } 19 | }) 20 | -------------------------------------------------------------------------------- /test/pa.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 'ਸਰੋਜਿਨੀ ਨਾਇਡੂ ਦਾ ਜਨਮ 13 ਫਰਵਰੀ 1879 ਨੂੰ ਭਾਰਤ ਦੇ ਸ਼ਹਿਰ ਹੈਦਰਾਬਾਦ ਵਿੱਚ ਹੋਇਆ ਸੀ। ਉਸ ਦੇ ਪਿਤਾ ਅਘੋਰਨਾਥ ਚੱਟੋਪਾਧਿਆਏ ਇੱਕ ਨਾਮੀ ਵਿਦਵਾਨ ਅਤੇ ਮਾਂ ਬਰਾਦਾ ਸੁੰਦਰੀ ਦੇਬੀ ਕਵਿਤਰੀ ਸੀ ਅਤੇ ਬੰਗਾਲੀ ਵਿੱਚ ਲਿਖਦੀ ਸੀ।': [ 6 | 'ਸਰੋਜਿਨੀ ਨਾਇਡੂ ਦਾ ਜਨਮ 13 ਫਰਵਰੀ 1879 ਨੂੰ ਭਾਰਤ ਦੇ ਸ਼ਹਿਰ ਹੈਦਰਾਬਾਦ ਵਿੱਚ ਹੋਇਆ ਸੀ।', 7 | 'ਉਸ ਦੇ ਪਿਤਾ ਅਘੋਰਨਾਥ ਚੱਟੋਪਾਧਿਆਏ ਇੱਕ ਨਾਮੀ ਵਿਦਵਾਨ ਅਤੇ ਮਾਂ ਬਰਾਦਾ ਸੁੰਦਰੀ ਦੇਬੀ ਕਵਿਤਰੀ ਸੀ ਅਤੇ ਬੰਗਾਲੀ ਵਿੱਚ ਲਿਖਦੀ ਸੀ।' 8 | ] 9 | } 10 | 11 | describe('Punjabi segment()', function () { 12 | for (const [text, expectedSentences] of Object.entries(tests)) { 13 | it(`correctly segments text: ${text}`, function () { 14 | const sentences = segment('pa', text) 15 | assert.deepEqual(sentences, expectedSentences) 16 | }) 17 | } 18 | }) 19 | -------------------------------------------------------------------------------- /test/nl.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 6 | 'Hij schoot op de JP8-brandstof toen de Surface-to-Air (sam)-missiles op hem af kwamen. 81 procent van de schoten was raak.': 7 | [ 8 | 'Hij schoot op de JP8-brandstof toen de Surface-to-Air (sam)-missiles op hem af kwamen.', 9 | '81 procent van de schoten was raak.' 10 | ], 11 | '81 procent van de schoten was raak. ...en toen barste de hel los.': ['81 procent van de schoten was raak.', '...', 'en toen barste de hel los.'], 12 | 13 | 'Afkorting aanw. vnw.': ['Afkorting aanw. vnw.'] 14 | 15 | } 16 | 17 | describe('Dutch segment()', function () { 18 | for (const [text, expectedSentences] of Object.entries(tests)) { 19 | it(`correctly segments text: ${text}`, function () { 20 | const sentences = segment('nl', text) 21 | assert.deepEqual(sentences, expectedSentences) 22 | }) 23 | } 24 | }) 25 | -------------------------------------------------------------------------------- /src/languages/ml.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | import English from './en.js' 3 | 4 | const abbreviations = new Set([ 5 | ...English.abbreviations, 6 | 'ഡോ', // Dr 7 | 'Dr', 8 | 'പ്രൊ', // Prof 9 | 'പ്രൊഫ', // Prof 10 | 'മി', // Mr, or Minister 11 | 'ശ്രീ', // Formal addressing - male 12 | 'ശ്രീമതി', // Formal addressing - female 13 | 'ബഹു', // Respected 14 | // Transliteration of English alphabets 15 | 'എ', 16 | 'ബി', 17 | 'സി', 18 | 'ഡി', 19 | 'എഫ്', 20 | 'ജി', 21 | 'എച്', 22 | 'എച്ച്', 23 | 'ഐ', 24 | 'ജെ', 25 | 'കെ', 26 | 'എൽ', 27 | 'എം', 28 | 'എൻ', 29 | 'ഒ', 30 | 'ഓ', 31 | 'പി', 32 | 'ക്യു', 33 | 'ക്യൂ', 34 | 'ആർ', 35 | 'എസ്', 36 | 'ടി', 37 | 'യു', 38 | 'യൂ', 39 | 'വി', 40 | 'ഡബ്ല്യു', 41 | 'ഡബ്ള്യു', 42 | 'എക്സ്', 43 | 'വൈ', 44 | 'ഇസഡ്' 45 | ]) 46 | 47 | export default class Malayalam extends BaseLanguage { 48 | static abbreviations = abbreviations 49 | } 50 | -------------------------------------------------------------------------------- /test/mr.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 'आज दसरा आहे. आज खूप शुभ दिवस आहे.': ['आज दसरा आहे.', 'आज खूप शुभ दिवस आहे.'], 6 | 'ढग खूप गर्जत होते; पण पाऊस पडत नव्हता.': ['ढग खूप गर्जत होते; पण पाऊस पडत नव्हता.'], 7 | 'रमाची परीक्षा कधी आहे? अवकाश आहे अजून.': ['रमाची परीक्षा कधी आहे?', 'अवकाश आहे अजून.'], 8 | 'शाब्बास, असाच अभ्यास कर! आणि मग तुला नक्की यश मिळणार.': ['शाब्बास, असाच अभ्यास कर!', 'आणि मग तुला नक्की यश मिळणार.'], 9 | '"आपली आपण करी स्तुती तो एक मूर्ख" असे समर्थ रामदासस्वामी म्हणतात.': ['"आपली आपण करी स्तुती तो एक मूर्ख" असे समर्थ रामदासस्वामी म्हणतात.'] 10 | } 11 | 12 | describe('Marathi segment()', function () { 13 | for (const [text, expectedSentences] of Object.entries(tests)) { 14 | it(`correctly segments text: ${text}`, function () { 15 | const sentences = segment('mr', text) 16 | assert.deepEqual(sentences, expectedSentences) 17 | }) 18 | } 19 | }) 20 | -------------------------------------------------------------------------------- /.github/workflows/nodejs.yaml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Node.js CI 5 | 6 | on: 7 | push: 8 | branches: [ main ] 9 | pull_request: 10 | branches: [ main ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | strategy: 18 | matrix: 19 | node-version: [16.x, 18.x, 20.x] 20 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 21 | 22 | steps: 23 | - uses: actions/checkout@v2 24 | - name: Use Node.js ${{ matrix.node-version }} 25 | uses: actions/setup-node@v2 26 | with: 27 | node-version: ${{ matrix.node-version }} 28 | - run: npm install 29 | - run: npm run build --if-present 30 | - run: npm test 31 | -------------------------------------------------------------------------------- /test/ar.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 'ومن المنتظر أن يكتمل مشروع خط أنابيب نابوكو البالغ طوله 3300 كليومترا في 12‪/‬08‪/‬2014 بتكلفة تُقدر بـ 7.9 مليارات يورو أي نحو 10.9 مليارات دولار. ومن المقرر أن تصل طاقة ضخ الغاز في المشروع 31 مليار متر مكعب انطلاقا من بحر قزوين مرورا بالنمسا وتركيا ودول البلقان دون المرور على الأراضي الروسية.': [ 6 | 'ومن المنتظر أن يكتمل مشروع خط أنابيب نابوكو البالغ طوله 3300 كليومترا في 12‪/‬08‪/‬2014 بتكلفة تُقدر بـ 7.9 مليارات يورو أي نحو 10.9 مليارات دولار.', 7 | 'ومن المقرر أن تصل طاقة ضخ الغاز في المشروع 31 مليار متر مكعب انطلاقا من بحر قزوين مرورا بالنمسا وتركيا ودول البلقان دون المرور على الأراضي الروسية.' 8 | ] 9 | } 10 | 11 | describe('Arabic segment()', function () { 12 | for (const [text, expectedSentences] of Object.entries(tests)) { 13 | it(`correctly segments text: ${text}`, function () { 14 | const sentences = segment('ar', text) 15 | assert.deepEqual(sentences, expectedSentences) 16 | }) 17 | } 18 | }) 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Santhosh Thottingal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /src/languages/bg.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | 3 | const abbreviations = new Set([ 4 | 'p.s', 5 | 'акад', 6 | 'ал', 7 | 'б.р', 8 | 'б.ред', 9 | 'бел.а', 10 | 'бел.пр', 11 | 'бр', 12 | 'бул', 13 | 'в', 14 | 'вж', 15 | 'вкл', 16 | 'вм', 17 | 'вр', 18 | 'г', 19 | 'ген', 20 | 'гр', 21 | 'дж', 22 | 'дм', 23 | 'доц', 24 | 'др', 25 | 'ем', 26 | 'заб', 27 | 'зам', 28 | 'инж', 29 | 'к.с', 30 | 'кв.м', 31 | 'кв', 32 | 'кг', 33 | 'км', 34 | 'кор', 35 | 'куб.м', 36 | 'куб', 37 | 'л', 38 | 'лв', 39 | 'м.г', 40 | 'м', 41 | 'мин', 42 | 'млн', 43 | 'млрд', 44 | 'мм', 45 | 'н.с', 46 | 'напр', 47 | 'пл', 48 | 'полк', 49 | 'проф', 50 | 'р', 51 | 'рис', 52 | 'с', 53 | 'св', 54 | 'сек', 55 | 'см', 56 | 'сп', 57 | 'срв', 58 | 'ст', 59 | 'стр', 60 | 'т.г', 61 | 'т.е', 62 | 'т.н', 63 | 'т.нар', 64 | 'т', 65 | 'табл', 66 | 'тел', 67 | 'у', 68 | 'ул', 69 | 'фиг', 70 | 'ха', 71 | 'хил', 72 | 'ч', 73 | 'чл', 74 | 'щ.д' 75 | 76 | ]) 77 | 78 | export default class Bulgarian extends BaseLanguage { 79 | static abbreviations = abbreviations 80 | } 81 | -------------------------------------------------------------------------------- /src/languages/ru.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | 3 | const abbreviations = new Set([ 4 | 'y.e', 5 | 'y', 6 | 'а', 7 | 'авт', 8 | 'адм.-терр', 9 | 'акад', 10 | 'в', 11 | 'вв', 12 | 'вкз', 13 | 'вост.-европ', 14 | 'г', 15 | 'гг', 16 | 'гос', 17 | 'гр', 18 | 'д', 19 | 'деп', 20 | 'дисс', 21 | 'дол', 22 | 'долл', 23 | 'ежедн', 24 | 'ж', 25 | 'жен', 26 | 'з', 27 | 'зап.-европ', 28 | 'зап', 29 | 'заруб', 30 | 'и', 31 | 'ин', 32 | 'иностр', 33 | 'инст', 34 | 'к', 35 | 'канд', 36 | 'кв', 37 | 'кг', 38 | 'куб', 39 | 'л.h', 40 | 'л.н', 41 | 'л', 42 | 'м', 43 | 'мин', 44 | 'моск', 45 | 'муж', 46 | 'н', 47 | 'нед', 48 | 'о', 49 | 'п', 50 | 'пгт', 51 | 'пер', 52 | 'пп', 53 | 'пр', 54 | 'просп', 55 | 'проф', 56 | 'р', 57 | 'руб', 58 | 'с', 59 | 'сек', 60 | 'см', 61 | 'спб', 62 | 'стр', 63 | 'т', 64 | 'тел', 65 | 'тов', 66 | 'тт', 67 | 'тыс', 68 | 'у.е', 69 | 'у', 70 | 'ул', 71 | 'ф', 72 | 'ч' 73 | ]) 74 | 75 | export default class Russian extends BaseLanguage { 76 | static abbreviations = abbreviations 77 | 78 | continueInNextWord (textAfterBoundary) { 79 | return textAfterBoundary.match(/^[0-9a-zа-я]/) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/languages/ta.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | import English from './en.js' 3 | 4 | const vowelSigns = new Set(['ா', 'ி', 'ீ', 'ு', 'ூ', 'ெ', 'ே', 'ை', 'ொ', 'ோ', 'ௌ']) 5 | const vowels = new Set(['அ', 'ஆ', 'இ', 'ஈ', 'உ', 'ஊ', 'எ', 'ஏ', 'ஐ', 'ஒ', 'ஓ', 'ஔ']) 6 | const consonants = new Set([ 7 | 'க', 8 | 'ங', 9 | 'ச', 10 | 'ஞ', 11 | 'ட', 12 | 'ண', 13 | 'த', 14 | 'ந', 15 | 'ப', 16 | 'ம', 17 | 'ய', 18 | 'ர', 19 | 'ல', 20 | 'வ', 21 | 'ழ', 22 | 'ள', 23 | 'ற', 24 | 'ன' 25 | ]) 26 | 27 | const consonantVowels = new Set() 28 | 29 | for (const consonant of consonants) { 30 | for (const vowelSign of vowelSigns) { 31 | consonantVowels.add(consonant + vowelSign) 32 | } 33 | } 34 | 35 | const abbreviations = new Set([ 36 | ...English.abbreviations, 37 | ...vowels, 38 | ...consonants, 39 | ...consonantVowels, 40 | 'ஏ', 41 | 'பி', 42 | 'சி', 43 | 'டி', 44 | 'ஈ', 45 | 'எஃப்', 46 | 'ஜி', 47 | 'ஹேச்', 48 | 'ஐ', 49 | 'ஜே', 50 | 'கே', 51 | 'எல்', 52 | 'எம்', 53 | 'என்', 54 | 'ஓ', 55 | // "பி", 56 | 'க்யூ', 57 | 'ஆர்', 58 | 'எஸ்', 59 | // "டி", 60 | 'யூ', 61 | 'வி', 62 | 'டபிள்யூ', 63 | 'எக்ஸ்', 64 | 'வை', 65 | 'ஜெட்' 66 | ]) 67 | 68 | export default class Tamil extends BaseLanguage { 69 | static abbreviations = abbreviations 70 | } 71 | -------------------------------------------------------------------------------- /test/sk.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 6 | 'Ide o majiteľov firmy ABTrade s. r. o., ktorí stoja aj za ďalšími spoločnosťami, napr. XYZCorp a.s.': 7 | [ 8 | 'Ide o majiteľov firmy ABTrade s. r. o., ktorí stoja aj za ďalšími spoločnosťami, napr. XYZCorp a.s.' 9 | ], 10 | 11 | '„Prieskumy beriem na ľahkú váhu. V podstate ma to nezaujíma,“ reagoval Matovič na prieskum agentúry Focus.': 12 | [ 13 | '„Prieskumy beriem na ľahkú váhu. V podstate ma to nezaujíma,“ reagoval Matovič na prieskum agentúry Focus.' 14 | ], 15 | 16 | 'Toto sa mi podarilo až na 10. pokus, ale stálo to za to.': 17 | ['Toto sa mi podarilo až na 10. pokus, ale stálo to za to.'], 18 | 19 | 'Ide o príslušníkov XII. Pluku špeciálneho určenia.': 20 | ['Ide o príslušníkov XII. Pluku špeciálneho určenia.'], 21 | 'Spoločnosť bola založená 7. Apríla 2020, na zmluve však figuruje dátum 20. marec 2020.': 22 | ['Spoločnosť bola založená 7. Apríla 2020, na zmluve však figuruje dátum 20. marec 2020.'] 23 | } 24 | 25 | describe('Slovak segment()', function () { 26 | for (const [text, expectedSentences] of Object.entries(tests)) { 27 | it(`correctly segments text: ${text}`, function () { 28 | const sentences = segment('sk', text) 29 | assert.deepEqual(sentences, expectedSentences) 30 | }) 31 | } 32 | }) 33 | -------------------------------------------------------------------------------- /test/pt.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 6 | 'A Lei do Sorteio (n.º 1860, de 4 de janeiro de 1908) introduziu o serviço militar obrigatório para as Forças Armadas do Brasil, implantado de fato em 1916, substituindo o recrutamento forçado, o antigo “tributo de sangue”, e permitindo a constituição de uma reserva.': 7 | [ 8 | 'A Lei do Sorteio (n.º 1860, de 4 de janeiro de 1908) introduziu o serviço militar obrigatório para as Forças Armadas do Brasil, implantado de fato em 1916, substituindo o recrutamento forçado, o antigo “tributo de sangue”, e permitindo a constituição de uma reserva.' 9 | ], 10 | 11 | 'Os oficiais mantinham a disciplina pelo castigo corporal.[13] Na Marinha, isso resultou na Revolta da Chibata de 1910.[14]': 12 | [ 13 | 'Os oficiais mantinham a disciplina pelo castigo corporal.[13]', 14 | 'Na Marinha, isso resultou na Revolta da Chibata de 1910.[14]' 15 | ], 16 | 17 | 'A nova legislação era a lei 2.556, de 26 de setembro de 1874, e o decreto 5.881, de 17 de fevereiro de 1875.[35]': 18 | [ 19 | 'A nova legislação era a lei 2.556, de 26 de setembro de 1874, e o decreto 5.881, de 17 de fevereiro de 1875.[35]' 20 | ] 21 | } 22 | 23 | describe('Portuguese segment()', function () { 24 | for (const [text, expectedSentences] of Object.entries(tests)) { 25 | it(`correctly segments text: ${text}`, function () { 26 | const sentences = segment('pt', text) 27 | assert.deepEqual(sentences, expectedSentences) 28 | }) 29 | } 30 | }) 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sentencex", 3 | "version": "0.4.2", 4 | "description": "Sentence segmentation library", 5 | "main": "dist/cjs/index.cjs", 6 | "module": "dist/esm/index.js", 7 | "exports": { 8 | ".": { 9 | "require": "./dist/cjs/index.cjs", 10 | "import": "./dist/esm/index.js" 11 | } 12 | }, 13 | "type": "module", 14 | "scripts": { 15 | "build": "rollup -c", 16 | "lint": "eslint src test", 17 | "test:unit": "mocha", 18 | "test": "npm run lint && npm run test:unit" 19 | }, 20 | "bin": { 21 | "segment": "bin/segment.mjs" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "git+https://github.com/santhoshtr/sentencex-js.git" 26 | }, 27 | "keywords": [ 28 | "nlp", 29 | "sentence-segmentation" 30 | ], 31 | "author": "Santhosh Thottingal", 32 | "license": "MIT", 33 | "bugs": { 34 | "url": "https://github.com/santhoshtr/sentencex-js/issues" 35 | }, 36 | "homepage": "https://github.com/santhoshtr/sentencex-js#readme", 37 | "engines": { 38 | "node": ">=14" 39 | }, 40 | "devDependencies": { 41 | "@babel/eslint-parser": "^7.22.15", 42 | "@babel/plugin-syntax-import-assertions": "^7.22.5", 43 | "@rollup/plugin-json": "^6.0.0", 44 | "eslint-config-standard": "^17.1.0", 45 | "eslint-plugin-import": "^2.28.1", 46 | "eslint-plugin-n": "^16.1.0", 47 | "eslint-plugin-promise": "^6.1.1", 48 | "eslint": "^8.50.0", 49 | "mocha": "^10.2.0", 50 | "prettier": "^3.0.3", 51 | "rollup-plugin-esbuild": "^6.0.0", 52 | "rollup": "^3.29.3" 53 | }, 54 | "dependencies": {} 55 | } 56 | -------------------------------------------------------------------------------- /src/languages/index.js: -------------------------------------------------------------------------------- 1 | import Amharic from './am.js' 2 | import Arabic from './ar.js' 3 | import Armenian from './hy.js' 4 | import Bengali from './bn.js' 5 | import Bulgarian from './bg.js' 6 | import Burmese from './my.js' 7 | import Catalan from './ca.js' 8 | import Danish from './da.js' 9 | import Deutsch from './de.js' 10 | import Dutch from './nl.js' 11 | import English from './en.js' 12 | import Finnish from './fi.js' 13 | import French from './fr.js' 14 | import Greek from './el.js' 15 | import Gujarati from './gu.js' 16 | import Hindi from './hi.js' 17 | import Japanese from './ja.js' 18 | import Kannada from './kn.js' 19 | import Kazakh from './kk.js' 20 | import Malayalam from './ml.js' 21 | import Marathi from './mr.js' 22 | import Odia from './or.js' 23 | import Polish from './pl.js' 24 | import Portuguese from './pt.js' 25 | import Punjabi from './pa.js' 26 | import Russian from './ru.js' 27 | import Slovak from './sk.js' 28 | import Spanish from './es.js' 29 | import Tamil from './ta.js' 30 | import Telugu from './te.js' 31 | 32 | export default { 33 | am: Amharic, 34 | ar: Arabic, 35 | bg: Bulgarian, 36 | bn: Bengali, 37 | ca: Catalan, 38 | da: Danish, 39 | de: Deutsch, 40 | el: Greek, 41 | en: English, 42 | es: Spanish, 43 | fi: Finnish, 44 | fr: French, 45 | gu: Gujarati, 46 | hi: Hindi, 47 | hy: Armenian, 48 | ja: Japanese, 49 | kk: Kazakh, 50 | kn: Kannada, 51 | ml: Malayalam, 52 | mr: Marathi, 53 | my: Burmese, 54 | nl: Dutch, 55 | or: Odia, 56 | pa: Punjabi, 57 | pl: Polish, 58 | pt: Portuguese, 59 | ru: Russian, 60 | sk: Slovak, 61 | ta: Tamil, 62 | te: Telugu 63 | } 64 | -------------------------------------------------------------------------------- /src/languages/fr.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | 3 | const abbreviations = new Set([ 4 | 'a.c.n', 5 | 'a.m', 6 | 'al', 7 | 'ann', 8 | 'apr', 9 | 'art', 10 | 'auj', 11 | 'av', 12 | 'b.p', 13 | 'boul', 14 | 'c.-à-d', 15 | 'c.n.s', 16 | 'c.n', 17 | 'c.p.i', 18 | 'c.q.f.d', 19 | 'c.s', 20 | 'ca', 21 | 'cf', 22 | 'ch.-l', 23 | 'chap', 24 | 'co', 25 | 'contr', 26 | 'dir', 27 | 'e.g', 28 | 'e.v', 29 | 'éd', 30 | 'env', 31 | 'etc', 32 | 'ex', 33 | 'fasc', 34 | 'fém', 35 | 'fig', 36 | 'fr', 37 | 'hab', 38 | 'i.e', 39 | 'ibid', 40 | 'id', 41 | 'inf', 42 | 'l.d', 43 | 'lib', 44 | 'll.aa.ii', 45 | 'll.aa.rr', 46 | 'll.aa.ss', 47 | 'll.aa', 48 | 'll.ee', 49 | 'll.mm.ii.rr', 50 | 'll.mm', 51 | 'loc.cit', 52 | 'ltd', 53 | 'masc', 54 | 'mm', 55 | 'ms', 56 | 'n.b', 57 | 'n.d.a', 58 | 'n.d.l.r', 59 | 'n.d.t', 60 | 'n.d', 61 | 'n.p.a.i', 62 | 'n.s', 63 | 'n/réf', 64 | 'nn.ss', 65 | 'p.c.c', 66 | 'p.ex', 67 | 'p.j', 68 | 'p.s', 69 | 'pl', 70 | 'pp', 71 | 'r.-v', 72 | 'r.a.s', 73 | 'r.i.p', 74 | 'r.p', 75 | 's.a.i', 76 | 's.a.r', 77 | 's.a.s', 78 | 's.a', 79 | 's.e', 80 | 's.m.i.r', 81 | 's.m', 82 | 's.s', 83 | 'sec', 84 | 'sect', 85 | 'sing', 86 | 'sq', 87 | 'sqq', 88 | 'ss', 89 | 'suiv', 90 | 'sup', 91 | 'suppl', 92 | 't.s.v.p', 93 | 'tél', 94 | 'vb', 95 | 'vol', 96 | 'vs', 97 | 'x.o', 98 | 'z.i' 99 | 100 | ]) 101 | 102 | export default class French extends BaseLanguage { 103 | static abbreviations = abbreviations 104 | } 105 | -------------------------------------------------------------------------------- /src/languages/pt.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | 3 | const romanNumerals = 'i ii iii iv v vi vii viii ix x xi xii xiii xiv x xi xii xiii xv xvi xvii xviii xix xx' 4 | 5 | const romanNumeralsSet = new Set([...romanNumerals.split(' '), ...romanNumerals.toUpperCase().split(' ')]) 6 | 7 | const abbreviations = new Set([ 8 | ...romanNumeralsSet, 9 | 'Adj', 10 | 'Adm', 11 | 'Adv', 12 | 'Art', 13 | 'Ca', 14 | 'Capt', 15 | 'Cmdr', 16 | 'Col', 17 | 'Comdr', 18 | 'Con', 19 | 'Corp', 20 | 'Cpl', 21 | 'DR', 22 | 'DRA', 23 | 'Dr', 24 | 'Dra', 25 | 'Dras', 26 | 'Drs', 27 | 'Eng', 28 | 'Enga', 29 | 'Engas', 30 | 'Engos', 31 | 'Ex', 32 | 'Exo', 33 | 'Exmo', 34 | 'Fig', 35 | 'Gen', 36 | 'Hosp', 37 | 'Insp', 38 | 'Lda', 39 | 'MM', 40 | 'MR', 41 | 'MRS', 42 | 'MS', 43 | 'Maj', 44 | 'Mrs', 45 | 'Ms', 46 | 'Msgr', 47 | 'Op', 48 | 'Ord', 49 | 'Pfc', 50 | 'Ph', 51 | 'Prof', 52 | 'Pvt', 53 | 'Rep', 54 | 'Reps', 55 | 'Res', 56 | 'Rev', 57 | 'Rt', 58 | 'Sen', 59 | 'Sens', 60 | 'Sfc', 61 | 'Sgt', 62 | 'Sr', 63 | 'Sra', 64 | 'Sras', 65 | 'Srs', 66 | 'Sto', 67 | 'Supt', 68 | 'Surg', 69 | 'adj', 70 | 'adm', 71 | 'adv', 72 | 'art', 73 | 'cit', 74 | 'col', 75 | 'con', 76 | 'corp', 77 | 'cpl', 78 | 'dr', 79 | 'dra', 80 | 'dras', 81 | 'drs', 82 | 'eng', 83 | 'enga', 84 | 'engas', 85 | 'engos', 86 | 'ex', 87 | 'exo', 88 | 'exmo', 89 | 'fig', 90 | 'op', 91 | 'prof', 92 | 'sr', 93 | 'sra', 94 | 'sras', 95 | 'srs', 96 | 'sto', 97 | 'v', 98 | 'vs', 99 | 'i.e', 100 | 'rev', 101 | 'e.g' 102 | ]) 103 | 104 | export default class Portuguese extends BaseLanguage { 105 | static abbreviations = abbreviations 106 | } 107 | -------------------------------------------------------------------------------- /test/fi.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 6 | 'Se julkaistiin singlenä 7. heinäkuuta 1997, ja se nousi listaykköseksi yhtyeen kotimaassa Britanniassa sekä Irlannissa, Suomessa, Espanjassa ja Kanadassa': [ 7 | 'Se julkaistiin singlenä 7. heinäkuuta 1997, ja se nousi listaykköseksi yhtyeen kotimaassa Britanniassa sekä Irlannissa, Suomessa, Espanjassa ja Kanadassa' 8 | ], 9 | 10 | 'Brittiläinen musiikkilehti NME valitsi lokakuussa 2011 ”D’You Know What I Meanin?” sijalle 77 listallaan, joka sisälsi 150 parasta kappaletta vuosilta 1996–2011.': 11 | [ 12 | 'Brittiläinen musiikkilehti NME valitsi lokakuussa 2011 ”D’You Know What I Meanin?” sijalle 77 listallaan, joka sisälsi 150 parasta kappaletta vuosilta 1996–2011.' 13 | ], 14 | 'Netistä ladattu musiikki on otettu huomioon singlelistalla 3. lokakuuta 2007 lähtien.[13] Uudistus muutti listan luonnetta.': 15 | [ 16 | 'Netistä ladattu musiikki on otettu huomioon singlelistalla 3. lokakuuta 2007 lähtien.[13]', 17 | 'Uudistus muutti listan luonnetta.' 18 | ], 19 | 'Radiomafia oli Yleisradion pääasiassa nuorille ja nuorille aikuisille suunnattu radiokanava, joka aloitti toimintansa vuoden 1990 radiouudistuksessa 1. kesäkuuta 1990 ja lopetti Ylen radiouudistuksen myötä 12. tammikuuta 2003.': 20 | [ 21 | 'Radiomafia oli Yleisradion pääasiassa nuorille ja nuorille aikuisille suunnattu radiokanava, joka aloitti toimintansa vuoden 1990 radiouudistuksessa 1. kesäkuuta 1990 ja lopetti Ylen radiouudistuksen myötä 12. tammikuuta 2003.' 22 | ], 23 | 'Dr. Alban (oikealta nimeltä Alban Uzoma Nwapa, s. 26. elokuuta 1957 Oguta, Brittiläinen Nigeria) on nigerialaissyntyinen ruotsalainen eurodance/rap/reggae -artisti.': 24 | [ 25 | 'Dr. Alban (oikealta nimeltä Alban Uzoma Nwapa, s. 26. elokuuta 1957 Oguta, Brittiläinen Nigeria) on nigerialaissyntyinen ruotsalainen eurodance/rap/reggae -artisti.' 26 | ] 27 | 28 | } 29 | 30 | describe('Finnish segment()', function () { 31 | for (const [text, expectedSentences] of Object.entries(tests)) { 32 | it(`correctly segments text: ${text}`, function () { 33 | const sentences = segment('fi', text) 34 | assert.deepEqual(sentences, expectedSentences) 35 | }) 36 | } 37 | }) 38 | -------------------------------------------------------------------------------- /test/bg.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 6 | 'В първата половина на ноември т.г. ще бъде свикан Консултативният съвет за национална сигурност, обяви държавният глава.': 7 | [ 8 | 'В първата половина на ноември т.г. ще бъде свикан Консултативният съвет за национална сигурност, обяви държавният глава.' 9 | ], 10 | 11 | 'Компютърът е устройство с общо предназначение, което може да бъде програмирано да извършва набор от аритметични и/или логически операции. Възможността поредицата такива операции да бъде променяна позволява компютърът да се използва за решаването на теоретично всяка изчислителна/логическа задача. Обикновено целта на тези операции е обработката на въведена информация (данни), представена в цифров (дигитален) вид, резултатът от които може да се изведе в най-общо казано използваема форма.': 12 | [ 13 | 'Компютърът е устройство с общо предназначение, което може да бъде програмирано да извършва набор от аритметични и/или логически операции.', 14 | 'Възможността поредицата такива операции да бъде променяна позволява компютърът да се използва за решаването на теоретично всяка изчислителна/логическа задача.', 15 | 'Обикновено целта на тези операции е обработката на въведена информация (данни), представена в цифров (дигитален) вид, резултатът от които може да се изведе в най-общо казано използваема форма.' 16 | ], 17 | 'Пл. "20 Април"': ['Пл. "20 Април"'], 18 | 'Той поставя началото на могъща династия, която управлява в продължение на 150 г. Саргон надделява в двубой с владетеля на град Ур и разширява териториите на държавата си по долното течение на Тигър и Ефрат. Стойностни, вкл. български и руски': 19 | [ 20 | 'Той поставя началото на могъща династия, която управлява в продължение на 150 г. Саргон надделява в двубой с владетеля на град Ур и разширява териториите на държавата си по долното течение на Тигър и Ефрат.', 21 | 'Стойностни, вкл. български и руски' 22 | ] 23 | 24 | } 25 | 26 | describe('Bulgarian segment()', function () { 27 | for (const [text, expectedSentences] of Object.entries(tests)) { 28 | it(`correctly segments text: ${text}`, function () { 29 | const sentences = segment('bg', text) 30 | assert.deepEqual(sentences, expectedSentences) 31 | }) 32 | } 33 | }) 34 | -------------------------------------------------------------------------------- /src/languages/pl.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | 3 | const abbreviations = new Set([ 4 | 'ags', 5 | 'alb', 6 | 'ang', 7 | 'aor', 8 | 'awest', 9 | 'bałt', 10 | 'bojkow', 11 | 'bret', 12 | 'brus', 13 | 'bsł', 14 | 'bułg', 15 | 'c.b.d.o', 16 | 'c.b.d.u', 17 | 'celt', 18 | 'chorw', 19 | 'cs', 20 | 'czakaw', 21 | 'czerw', 22 | 'czes', 23 | 'dłuż', 24 | 'dniem', 25 | 'dor', 26 | 'dubrow', 27 | 'duń', 28 | 'ekaw', 29 | 'fiń', 30 | 'franc', 31 | 'gal', 32 | 'germ', 33 | 'głuż', 34 | 'gniem', 35 | 'goc', 36 | 'gr', 37 | 'grudz', 38 | 'hebr', 39 | 'het', 40 | 'hol', 41 | 'I cont', 42 | 'ie', 43 | 'ikaw', 44 | 'irań', 45 | 'irl', 46 | 'islandz', 47 | 'itd', 48 | 'itd.', 49 | 'itp', 50 | 'jekaw', 51 | 'kajkaw', 52 | 'kasz', 53 | 'kirg', 54 | 'kwiec', 55 | 'łac', 56 | 'lip', 57 | 'listop', 58 | 'lit', 59 | 'łot', 60 | 'lp', 61 | 'maced', 62 | 'mar', 63 | 'młpol', 64 | 'moraw', 65 | 'n.e', 66 | 'nb.', 67 | 'ngr', 68 | 'niem', 69 | 'nord', 70 | 'norw', 71 | 'np', 72 | 'np.', 73 | 'ok.', 74 | 'orm', 75 | 'oset', 76 | 'osk', 77 | 'p.n', 78 | 'p.n.e', 79 | 'p.o', 80 | 'pazdz', 81 | 'pers', 82 | 'pie', 83 | 'pod red.', 84 | 'podhal', 85 | 'pol', 86 | 'połab', 87 | 'port', 88 | 'prekm', 89 | 'pskow', 90 | 'psł', 91 | 'R cont', 92 | 'rez', 93 | 'rom', 94 | 'rozdz.', 95 | 'rum', 96 | 'rus', 97 | 'rys.', 98 | 'sas', 99 | 'sch', 100 | 'scs', 101 | 'serb', 102 | 'sierp', 103 | 'śl', 104 | 'sła', 105 | 'słe', 106 | 'słi', 107 | 'słow', 108 | 'sp. z o.o', 109 | 'śrdniem', 110 | 'śrgniem', 111 | 'śrirl', 112 | 'stbułg', 113 | 'stind', 114 | 'stpol', 115 | 'stpr', 116 | 'str.', 117 | 'strus', 118 | 'stwniem', 119 | 'stycz', 120 | 'sztokaw', 121 | 'szwedz', 122 | 't.', 123 | 'tj.', 124 | 'tłum.', 125 | 'toch', 126 | 'tur', 127 | 'tzn', 128 | 'ukr', 129 | 'ul', 130 | 'umbr', 131 | 'wed', 132 | 'węg', 133 | 'wlkpol', 134 | 'włos', 135 | 'wrzes', 136 | 'wyd.', 137 | 'zakarp' 138 | ]) 139 | 140 | export default class Polish extends BaseLanguage { 141 | static abbreviations = abbreviations 142 | constructor () { 143 | super() 144 | this.language = 'pl' 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /test/fr.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 6 | "Après avoir été l'un des acteurs du projet génome humain, le Genoscope met aujourd'hui le cap vers la génomique environnementale. L'exploitation des données de séquences, prolongée par l'identification expérimentale des fonctions biologiques, notamment dans le domaine de la biocatalyse, ouvrent des perspectives de développements en biotechnologie industrielle.": 7 | [ 8 | "Après avoir été l'un des acteurs du projet génome humain, le Genoscope met aujourd'hui le cap vers la génomique environnementale.", 9 | "L'exploitation des données de séquences, prolongée par l'identification expérimentale des fonctions biologiques, notamment dans le domaine de la biocatalyse, ouvrent des perspectives de développements en biotechnologie industrielle." 10 | ], 11 | 12 | "\"Airbus livrera comme prévu 30 appareils 380 cette année avec en ligne de mire l'objectif d'équilibre financier du programme en 2015\", a-t-il ajouté.": 13 | [ 14 | "\"Airbus livrera comme prévu 30 appareils 380 cette année avec en ligne de mire l'objectif d'équilibre financier du programme en 2015\", a-t-il ajouté." 15 | ], 16 | 17 | 'À 11 heures ce matin, la direction ne décomptait que douze grévistes en tout sur la France : ce sont ceux du site de Saran (Loiret), dont l’effectif est de 809 salariés, dont la moitié d’intérimaires. Elle assure que ce mouvement « n’aura aucun impact sur les livraisons ».': 18 | [ 19 | 'À 11 heures ce matin, la direction ne décomptait que douze grévistes en tout sur la France : ce sont ceux du site de Saran (Loiret), dont l’effectif est de 809 salariés, dont la moitié d’intérimaires.', 20 | 'Elle assure que ce mouvement « n’aura aucun impact sur les livraisons ».' 21 | ], 22 | 23 | 'Ce modèle permet d’afficher le texte « LL.AA.II.RR. » pour l’abréviation de « Leurs Altesses impériales et royales » avec son infobulle.': 24 | [ 25 | 'Ce modèle permet d’afficher le texte « LL.AA.II.RR. » pour l’abréviation de « Leurs Altesses impériales et royales » avec son infobulle.' 26 | ], 27 | 28 | 'Les derniers ouvrages de Intercept Ltd. sont ici.': 29 | ['Les derniers ouvrages de Intercept Ltd. sont ici.'] 30 | 31 | } 32 | 33 | describe('French segment()', function () { 34 | for (const [text, expectedSentences] of Object.entries(tests)) { 35 | it(`correctly segments text: ${text}`, function () { 36 | const sentences = segment('fr', text) 37 | assert.deepEqual(sentences, expectedSentences) 38 | }) 39 | } 40 | }) 41 | -------------------------------------------------------------------------------- /test/ja.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 'これはペンです。それはマーカーです。': ['これはペンです。', 'それはマーカーです。'], 6 | 'それは何ですか?ペンですか?': ['それは何ですか?', 'ペンですか?'], 7 | '良かったね!すごい!': ['良かったね!', 'すごい!'], 8 | '自民党税制調査会の幹部は、「引き下げ幅は3.29%以上を目指すことになる」と指摘していて、今後、公明党と合意したうえで、30日に決定する与党税制改正大綱に盛り込むことにしています。2%台後半を目指すとする方向で最終調整に入りました。': 9 | [ 10 | '自民党税制調査会の幹部は、「引き下げ幅は3.29%以上を目指すことになる」と指摘していて、今後、公明党と合意したうえで、30日に決定する与党税制改正大綱に盛り込むことにしています。', 11 | '2%台後半を目指すとする方向で最終調整に入りました。' 12 | ], 13 | 'アンディ・ガトマンズ(英: Andi Gutmans、ヘブライ語: אנדי גוטמנס‎)はスイスにルーツを持つイスラエル人プログラマで、PHPの開発とゼンド・テクノロジーズの創業者の1人として知られている[1]。ハイファにあるイスラエル工科大学出身で、1997年に友人のゼーブ・スラスキーと共にPHP 3を開発した。1999年、PHP 4の中核である Zend Engine を開発し、ゼンド・テクノロジーズを創業。その後PHPの発展に関与し続け、PHP 5開発にも参加している[2]。なおZendという名称は、ガトマンズとスラスキーの名前(ZeevとAndi)を組み合わせたかばん語である[3]。 ハイファにあるイスラエル工科大学出身で、1997年に友人のゼーブ・スラスキーと共にPHP 3を開発した。1999年、PHP 4の中核である Zend Engine を開発し、ゼンド・テクノロジーズを創業。その後PHPの発展に関与し続け、PHP 5開発にも参加している[2]。なおZendという名称は、ガトマンズとスラスキーの名前(ZeevとAndi)を組み合わせたかばん語である[3]。': 14 | [ 15 | 'アンディ・ガトマンズ(英: Andi Gutmans、ヘブライ語: אנדי גוטמנס‎)はスイスにルーツを持つイスラエル人プログラマで、PHPの開発とゼンド・テクノロジーズの創業者の1人として知られている[1]。', 16 | 'ハイファにあるイスラエル工科大学出身で、1997年に友人のゼーブ・スラスキーと共にPHP 3を開発した。1999年、PHP 4の中核である Zend Engine を開発し、ゼンド・テクノロジーズを創業。', 17 | 'その後PHPの発展に関与し続け、PHP 5開発にも参加している[2]。', 18 | 'なおZendという名称は、ガトマンズとスラスキーの名前(ZeevとAndi)を組み合わせたかばん語である[3]。', 19 | 'ハイファにあるイスラエル工科大学出身で、1997年に友人のゼーブ・スラスキーと共にPHP 3を開発した。1999年、PHP 4の中核である Zend Engine を開発し、ゼンド・テクノロジーズを創業。', 20 | 'その後PHPの発展に関与し続け、PHP 5開発にも参加している[2]。', 21 | 'なおZendという名称は、ガトマンズとスラスキーの名前(ZeevとAndi)を組み合わせたかばん語である[3]。' 22 | ], 23 | 'ハイファにあるイスラエル工科大学出身で、1997年に友人のゼーブ・スラスキーと共にPHP 3を開発した。1999年、PHP 4の中核である Zend Engine を開発し、ゼンド・テクノロジーズを創業。その後PHPの発展に関与し続け、PHP 5開発にも参加している。なおZendという名称は、ガトマンズとスラスキーの名前(ZeevとAndi)を組み合わせたかばん語である。ハイファにあるイスラエル工科大学出身で、1997年に友人のゼーブ・スラスキーと共にPHP 3を開発した。1999年、PHP 4の中核である Zend Engine を開発し、ゼンド・テクノロジーズを創業。その後PHPの発展に関与し続け、PHP 5 開発にも参加している。なおZendという名称は、ガトマンズとスラスキーの名前(ZeevとAndi)を組み合わせたかばん語である。': 24 | [ 25 | 'ハイファにあるイスラエル工科大学出身で、1997年に友人のゼーブ・スラスキーと共にPHP 3を開発した。1999年、PHP 4の中核である Zend Engine を開発し、ゼンド・テクノロジーズを創業。', 26 | 'その後PHPの発展に関与し続け、PHP 5開発にも参加している。', 27 | 'なおZendという名称は、ガトマンズとスラスキーの名前(ZeevとAndi)を組み合わせたかばん語である。', 28 | 'ハイファにあるイスラエル工科大学出身で、1997年に友人のゼーブ・スラスキーと共にPHP 3を開発した。1999年、PHP 4の中核である Zend Engine を開発し、ゼンド・テクノロジーズを創業。', 29 | 'その後PHPの発展に関与し続け、PHP 5 開発にも参加している。', 30 | 'なおZendという名称は、ガトマンズとスラスキーの名前(ZeevとAndi)を組み合わせたかばん語である。' 31 | ] 32 | } 33 | 34 | describe('Japanese segment()', function () { 35 | for (const [text, expectedSentences] of Object.entries(tests)) { 36 | it(`correctly segments text: ${text}`, function () { 37 | const sentences = segment('ja', text) 38 | assert.deepEqual(sentences, expectedSentences) 39 | }) 40 | } 41 | }) 42 | -------------------------------------------------------------------------------- /src/languages/fi.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | 3 | const abbreviations = new Set([ 4 | 'A', 5 | 'B', 6 | 'C', 7 | 'D', 8 | 'E', 9 | 'F', 10 | 'G', 11 | 'H', 12 | 'I', 13 | 'J', 'K', 14 | 'L', 15 | 'M', 16 | 'N', 17 | 'O', 18 | 'P', 19 | 'Q', 20 | 'R', 21 | 'S', 22 | 'T', 23 | 'U', 24 | 'V', 25 | 'W', 26 | 'X', 27 | 'Y', 28 | 'Z', 29 | 'Å', 30 | 'Ä', 31 | 'Ö', 32 | // List of titles. 33 | // These are often followed by upper-case names, but do not indicate sentence breaks 34 | 'alik', 35 | 'alil', 36 | 'amir', 37 | 'apul', 38 | 'apul.prof', 39 | 'arkkit', 40 | 'ass', 41 | 'assist', 42 | 'dipl', 43 | 'dipl.arkkit', 44 | 'dipl.ekon', 45 | 'dipl.ins', 46 | 'dipl.kielenk', 47 | 'dipl.kirjeenv', 48 | 'dipl.kosm', 49 | 'dipl.urk', 50 | 'dos', 51 | 'Dr', 52 | 'erikoiseläinl', 53 | 'erikoishammasl', 54 | 'erikoisl', 55 | 'erikoist', 56 | 'ev.luutn', 57 | 'evp', 58 | 'fil', 59 | 'ft', 60 | 'hallinton', 61 | 'hallintot', 62 | 'hammaslääket', 63 | 'jatk', 64 | 'jääk', 65 | 'kansaned', 66 | 'kapt', 67 | 'kapt.luutn', 68 | 'kenr', 69 | 'kenr.luutn', 70 | 'kenr.maj', 71 | 'kers', 72 | 'kirjeenv', 73 | 'kom', 74 | 'kom.kapt', 75 | 'komm', 76 | 'konst', 77 | 'korpr', 78 | 'luutn', 79 | 'maist', 80 | 'maj', 81 | 'Mr', 82 | 'Mrs', 83 | 'Ms', 84 | 'M.Sc', 85 | 'neuv', 86 | 'nimim', 87 | 'Ph.D', 88 | 'prof', 89 | 'puh.joht', 90 | 'pääll', 91 | 'res', 92 | 'san', 93 | 'siht', 94 | 'suom', 95 | 'sähköp', 96 | 'säv', 97 | 'toht', 98 | 'toim', 99 | 'toim.apul', 100 | 'toim.joht', 101 | 'toim.siht', 102 | 'tuom', 103 | 'ups', 104 | 'vänr', 105 | 'vääp', 106 | 'ye.ups', 107 | 'ylik', 108 | 'ylil', 109 | 'ylim', 110 | 'ylimatr', 111 | 'yliop', 112 | 'yliopp', 113 | 'ylip', 114 | 'yliv', 115 | // misc - odd period-ending items that NEVER indicate breaks (p.m. does NOT fall 116 | // into this category - it sometimes ends a sentence) 117 | 'e.g', 118 | 'ent', 119 | 'esim', 120 | 'huom', 121 | 'i.e', 122 | 'ilm', 123 | 'l', 124 | 'mm', 125 | 'myöh', 126 | 'nk', 127 | 'nyk', 128 | 'par', 129 | 'po', 130 | 't', 131 | 'v' 132 | ]) 133 | 134 | export default class Finnish extends BaseLanguage { 135 | static abbreviations = abbreviations 136 | static MONTHS = new Set([ 137 | 'tammikuu', 138 | 'helmikuu', 139 | 'maaliskuu', 140 | 'huhtikuu', 141 | 'toukokuu', 142 | 'kesäkuu', 143 | 'heinäkuu', 144 | 'elokuu', 145 | 'syyskuu', 146 | 'lokakuu', 147 | 'marraskuu', 148 | 'joulukuu' 149 | ]) 150 | 151 | continueInNextWord (textAfterBoundary) { 152 | if (textAfterBoundary.match(/^\W*[0-9a-z]/)) { 153 | return true 154 | } 155 | 156 | const nextWord = textAfterBoundary.trim().split(' ')[0] 157 | 158 | if (!nextWord.length) { 159 | return false 160 | } 161 | if (Finnish.MONTHS.has(nextWord) || Finnish.MONTHS.has(nextWord[0].toUpperCase() + nextWord.slice(1))) { 162 | return true 163 | } 164 | 165 | return false 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > NOTE: 2 | > This repository is deprecated, The original [sentencex](https://github.com/santhoshtr/sentencex) library is written in Rust and has node bindings. The node library name and APIs are same. 3 | 4 | # Sentence segmenter 5 | 6 | [![tests](https://github.com/santhoshtr/sentencex-js/actions/workflows/nodejs.yaml/badge.svg)](https://github.com/santhoshtr/sentencex/actions/workflows/nodejs.yaml) 7 | [![npm version](https://img.shields.io/npm/v/sentencex.svg?style=flat)](https://www.npmjs.com/package/sentencex) 8 | 9 | A sentence segmentation library with wide language support optimized for speed and utility. 10 | 11 | This is a javascript port of [sentencex python library](https://github.com/santhoshtr/sentencex) 12 | 13 | ## Approach 14 | 15 | - If it's a period, it ends a sentence. 16 | - If the preceding token is in the hand-compiled list of abbreviations, then it doesn't end a sentence. 17 | 18 | However, it is not 'period' for many languages. So we will use a list of known punctuations that can cause a sentence break in as many languages as possible. 19 | 20 | We also collect a list of known, popular abbreviations in as many languages as possible. 21 | 22 | Sometimes, it is very hard to get the segmentation correct. In such cases this library is opinionated and prefer not segmenting than wrong segmentation. If two sentences are accidentally together, that is ok. It is better than sentence being split in middle. 23 | Avoid over engineering to get everything linguistically 100% accurate. 24 | 25 | This approach would be suitable for applications like text to speech, machine translation. 26 | 27 | Consider this example: `We make a good team, you and I. Did you see Albert I. Jones yesterday?` 28 | 29 | The accurate splitting of this sentence is 30 | `["We make a good team, you and I." ,"Did you see Albert I. Jones yesterday?"]` 31 | 32 | However, to achieve this level precision, complex rules need to be added and it could create side effects. Instead, if we just don't segment between `I. Did`, it is ok for most of downstream applications. 33 | 34 | The sentence segmentation in this library is **non-distructive**. This means, if the sentences are combined together, you can reconstruct the original text. Line breaks, punctuations and whitespaces are preserved in the output. 35 | 36 | ## Usage 37 | 38 | Install the library using 39 | 40 | ```bash 41 | npm install --save sentencex 42 | ``` 43 | 44 | Then, any text can be segmented as follows. 45 | 46 | ```javascript 47 | import segment from 'sentencex' 48 | 49 | text = ` 50 | The James Webb Space Telescope (JWST) is a space telescope specifically designed to conduct infrared astronomy. The U.S. National Aeronautics and Space Administration (NASA) led Webb's design and development") 51 | ` 52 | console.log(segment("en", text)) 53 | 54 | ``` 55 | 56 | The first argument is language code, second argument is text to segment. The `segment` method returns an array of identified sentences. 57 | 58 | ## Language support 59 | 60 | The aim is to support all languages where there is a wikipedia. Instead of falling back on English for languages not defined in the library, a fallback chain is used. The closest language which is defined in the library will be used. Fallbacks for ~244 languages are defined. 61 | 62 | ## License 63 | 64 | MIT license. See [License](./LICENSE) 65 | -------------------------------------------------------------------------------- /src/languages/en.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | 3 | const abbreviations = new Set([ 4 | 'A', 5 | 'adj', 6 | 'adm', 7 | 'adv', 8 | 'al', 9 | 'ala', 10 | 'alta', 11 | 'apr', 12 | 'arc', 13 | 'ariz', 14 | 'ark', 15 | 'art', 16 | 'assn', 17 | 'asst', 18 | 'attys', 19 | 'aug', 20 | 'ave', 21 | 'B', 22 | 'bart', 23 | 'bld', 24 | 'bldg', 25 | 'blvd', 26 | 'brig', 27 | 'bros', 28 | 'btw', 29 | 'C', 30 | 'cal', 31 | 'calif', 32 | 'capt', 33 | 'cl', 34 | 'cmdr', 35 | 'co', 36 | 'col', 37 | 'colo', 38 | 'comdr', 39 | 'con', 40 | 'conn', 41 | 'corp', 42 | 'cpl', 43 | 'cres', 44 | 'ct', 45 | 'd.phil', 46 | 'D', 47 | 'dak', 48 | 'dec', 49 | 'del', 50 | 'dept', 51 | 'det', 52 | 'dist', 53 | 'dr.phil', 54 | 'dr.philos', 55 | 'dr', 56 | 'drs', 57 | 'e.g', 58 | 'E', 59 | 'ens', 60 | 'esp', 61 | 'esq', 62 | 'etc', 63 | 'exp', 64 | 'expy', 65 | 'ext', 66 | 'F', 67 | 'feb', 68 | 'fed', 69 | 'fig', 70 | 'fla', 71 | 'ft', 72 | 'fwy', 73 | 'fy', 74 | 'G', 75 | 'ga', 76 | 'gen', 77 | 'gov', 78 | 'H', 79 | 'hon', 80 | 'hosp', 81 | 'hr', 82 | 'hway', 83 | 'hwy', 84 | 'i.e', 85 | 'I', 86 | 'ia', 87 | 'id', 88 | 'ida', 89 | 'ill', 90 | 'inc', 91 | 'ind', 92 | 'ing', 93 | 'insp', 94 | 'J', 95 | 'jan', 96 | 'jr', 97 | 'jul', 98 | 'jun', 99 | 'K', 100 | 'kan', 101 | 'kans', 102 | 'ken', 103 | 'ky', 104 | 'L', 105 | 'la', 106 | 'lt', 107 | 'ltd', 108 | 'M', 109 | 'maj', 110 | 'man', 111 | 'mar', 112 | 'mass', 113 | 'may', 114 | 'md', 115 | 'me', 116 | 'med', 117 | 'messrs', 118 | 'mex', 119 | 'mfg', 120 | 'mich', 121 | 'min', 122 | 'minn', 123 | 'miss', 124 | 'mlle', 125 | 'mm', 126 | 'mme', 127 | 'mo', 128 | 'mont', 129 | 'mr', 130 | 'mrs', 131 | 'ms', 132 | 'msgr', 133 | 'mssrs', 134 | 'mt', 135 | 'mtn', 136 | 'Nº', 137 | 'N°', 138 | 'No̱', 139 | 'No', 140 | 'N', 141 | 'neb', 142 | 'nebr', 143 | 'nev', 144 | 'no', 145 | 'nos', 146 | 'nov', 147 | 'nr', 148 | 'O', 149 | 'oct', 150 | 'ok', 151 | 'okla', 152 | 'ont', 153 | 'op', 154 | 'ord', 155 | 'ore', 156 | 'p', 157 | 'P', 158 | 'pa', 159 | 'pd', 160 | 'pde', 161 | 'penn', 162 | 'penna', 163 | 'pfc', 164 | 'ph.d', 165 | 'ph', 166 | 'pl', 167 | 'plz', 168 | 'pp', 169 | 'prof', 170 | 'pvt', 171 | 'Q', 172 | 'que', 173 | 'R', 174 | 'rd', 175 | 'ref', 176 | 'rep', 177 | 'reps', 178 | 'res', 179 | 'rev', 180 | 'rs', 181 | 'rt', 182 | 'S', 183 | 'sask', 184 | 'sec', 185 | 'sen', 186 | 'sens', 187 | 'sep', 188 | 'sept', 189 | 'sfc', 190 | 'sgt', 191 | 'sr', 192 | 'st', 193 | 'supt', 194 | 'surg', 195 | 'T', 196 | 'tce', 197 | 'tenn', 198 | 'tex', 199 | 'u.s', 200 | 'U', 201 | 'univ', 202 | 'usafa', 203 | 'ut', 204 | 'v', 205 | 'V', 206 | 'va', 207 | 'ver', 208 | 'viz', 209 | 'vs', 210 | 'vt', 211 | 'W', 212 | 'wash', 213 | 'wis', 214 | 'wisc', 215 | 'wy', 216 | 'wyo', 217 | 'X', 218 | 'Y', 219 | 'yuk', 220 | 'Z' 221 | ]) 222 | 223 | export default class English extends BaseLanguage { 224 | static abbreviations = abbreviations 225 | } 226 | -------------------------------------------------------------------------------- /test/kk.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 'Мұхитқа тікелей шыға алмайтын мемлекеттердің ішінде Қазақстан - ең үлкені.': 6 | ['Мұхитқа тікелей шыға алмайтын мемлекеттердің ішінде Қазақстан - ең үлкені.'], 7 | 8 | 'Әр түрлі өлшемнің атауы болып табылатын м (метр), см (сантиметр), кг (киллограмм), т (тонна), га (гектар), ц (центнер), т. б. (тағы басқа), тәрізді белгілер де қысқарған сөздер болып табылады.': 9 | [ 10 | 'Әр түрлі өлшемнің атауы болып табылатын м (метр), см (сантиметр), кг (киллограмм), т (тонна), га (гектар), ц (центнер), т. б. (тағы басқа), тәрізді белгілер де қысқарған сөздер болып табылады.' 11 | ], 12 | 13 | 'Мысалы: обкомға (облыстық комитетке) барды, ауаткомда (аудандық атқару комитетінде) болды, педучилищеге (педагогтік училищеге) түсті, медпункттің (медициналық пункттің) алдында т. б.': 14 | [ 15 | 'Мысалы: обкомға (облыстық комитетке) барды, ауаткомда (аудандық атқару комитетінде) болды, педучилищеге (педагогтік училищеге) түсті, медпункттің (медициналық пункттің) алдында т. б.' 16 | ], 17 | 'Елдің жалпы ішкі өнімі ЖІӨ (номинал) = $225.619 млрд (2014)': 18 | ['Елдің жалпы ішкі өнімі ЖІӨ (номинал) = $225.619 млрд (2014)'], 19 | 'Ресейдiң әлеуметтiк-экономикалық жағдайы.XVIII ғасырдың бiрiншi ширегiнде Ресейге тән нәрсе.': 20 | [ 21 | 'Ресейдiң әлеуметтiк-экономикалық жағдайы.', 22 | 'XVIII ғасырдың бiрiншi ширегiнде Ресейге тән нәрсе.' 23 | ], 24 | // '(«Егемен Қазақстан», 7 қыркүйек 2012 жыл. №590-591); Бұл туралы кеше санпедқадағалау комитетінің облыыстық департаменті хабарлады. («Айқын», 23 сəуір 2010 жыл. № 70).': 25 | // [ 26 | // '(«Егемен Қазақстан», 7 қыркүйек 2012 жыл. №590-591); Бұл туралы кеше санпедқадағалау комитетінің облыыстық департаменті хабарлады.', 27 | // '(«Айқын», 23 сəуір 2010 жыл. № 70).' 28 | // ], 29 | 'Иран революциясы (1905 — 11) және азаматтық қозғалыс (1918 — 21) кезінде А. Фарахани, М. Кермани, М. Т. Бехар, т.б. ақындар демократиялық идеяның жыршысы болды.': 30 | [ 31 | 'Иран революциясы (1905 — 11) және азаматтық қозғалыс (1918 — 21) кезінде А. Фарахани, М. Кермани, М. Т. Бехар, т.б. ақындар демократиялық идеяның жыршысы болды.' 32 | ], 33 | 'Владимир Федосеев: Аттар магиясы енді жоқ http://www.vremya.ru/2003/179/10/80980.html': 34 | ['Владимир Федосеев: Аттар магиясы енді жоқ http://www.vremya.ru/2003/179/10/80980.html'], 35 | 36 | 'Бірақ оның енді не керегі бар? — деді.': ['Бірақ оның енді не керегі бар? — деді.'], 37 | 38 | 'Сондықтан шапаныма жегізіп отырғаным! - деп, жауап береді.': 39 | ['Сондықтан шапаныма жегізіп отырғаным! - деп, жауап береді.'], 40 | 41 | 'Б.з.б. 6 – 3 ғасырларда конфуцийшілдік, моизм, легизм мектептерінің қалыптасуы нәтижесінде Қытай философиясы пайда болды.': 42 | [ 43 | 'Б.з.б. 6 – 3 ғасырларда конфуцийшілдік, моизм, легизм мектептерінің қалыптасуы нәтижесінде Қытай философиясы пайда болды.' 44 | ], 45 | 46 | "'Та марбута' тек сөз соңында екі түрде жазылады:": ["'Та марбута' тек сөз соңында екі түрде жазылады:"] 47 | 48 | } 49 | 50 | describe('Kazakh segment()', function () { 51 | for (const [text, expectedSentences] of Object.entries(tests)) { 52 | it(`correctly segments text: ${text}`, function () { 53 | const sentences = segment('kk', text) 54 | assert.deepEqual(sentences, expectedSentences) 55 | }) 56 | } 57 | }) 58 | -------------------------------------------------------------------------------- /src/languages/de.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | import English from './en.js' 3 | 4 | const abbreviations = new Set([ 5 | ...English.abbreviations, 6 | 'ä', 7 | 'Ä', 8 | 'adj', 9 | 'adm', 10 | 'adv', 11 | 'ao.univ.prof', 12 | 'art', 13 | 'ass.prof', 14 | 'ass', 15 | 'asst', 16 | 'b.a', 17 | 'b.s', 18 | 'bart', 19 | 'bldg', 20 | 'brig', 21 | 'bros', 22 | 'bse', 23 | 'buchst', 24 | 'bzgl', 25 | 'bzw', 26 | 'c.-à-d', 27 | 'ca', 28 | 'capt', 29 | 'chr', 30 | 'cmdr', 31 | 'co', 32 | 'col', 33 | 'comdr', 34 | 'con', 35 | 'corp', 36 | 'cpl', 37 | 'd.h', 38 | 'd.j', 39 | 'dergl', 40 | 'dgl', 41 | 'di', 42 | 'dipl.-ing', 43 | 'dkr', 44 | 'dr ', 45 | 'ens', 46 | 'etc', 47 | 'ev ', 48 | 'evtl', 49 | 'ff', 50 | 'g.g.a', 51 | 'g.u', 52 | 'gen', 53 | 'ggf', 54 | 'gov', 55 | 'hon.prof', 56 | 'hon', 57 | 'hosp', 58 | 'i.f', 59 | 'i.h.v', 60 | 'ii', 61 | 'iii', 62 | 'insp', 63 | 'iv', 64 | 'ix', 65 | 'jun', 66 | 'k.o', 67 | 'kath', 68 | 'lfd', 69 | 'lt', 70 | 'ltd', 71 | 'm.e', 72 | 'mag', 73 | 'maj', 74 | 'med', 75 | 'messrs', 76 | 'mio', 77 | 'mlle', 78 | 'mm', 79 | 'mme', 80 | 'mr', 81 | 'mrd', 82 | 'mrs', 83 | 'ms', 84 | 'msgr', 85 | 'mwst', 86 | 'no', 87 | 'nos', 88 | 'nr', 89 | 'o.ä', 90 | 'o.univ.-prof', 91 | 'op', 92 | 'ord', 93 | 'pfc', 94 | 'ph', 95 | 'pp', 96 | 'prof', 97 | 'projektass', 98 | 'pvt', 99 | 'rep', 100 | 'reps', 101 | 'res', 102 | 'rev', 103 | 'rt', 104 | 's', 105 | 's.p.a', 106 | 'sa', 107 | 'sen', 108 | 'sens', 109 | 'sfc', 110 | 'sgt', 111 | 'sog', 112 | 'sogen', 113 | 'spp', 114 | 'sr', 115 | 'st', 116 | 'std', 117 | 'str ', 118 | 'stud.ass', 119 | 'supt', 120 | 'surg', 121 | 'T', 122 | 'u.a ', 123 | 'u.ä', 124 | 'u.e', 125 | 'u.s.w', 126 | 'u.u', 127 | 'univ.-doz', 128 | 'univ.-prof', 129 | 'univ.ass', 130 | 'usf', 131 | 'usw', 132 | 'v', 133 | 'vgl', 134 | 'vi', 135 | 'vii', 136 | 'viii', 137 | 'vs', 138 | 'x', 139 | 'xi', 140 | 'xii', 141 | 'xiii', 142 | 'xiv', 143 | 'xix', 144 | 'xv', 145 | 'xvi', 146 | 'xvii', 147 | 'xviii', 148 | 'xx', 149 | 'z.b', 150 | 'z.t', 151 | 'z.z', 152 | 'z.zt', 153 | 'zt', 154 | 'zzt' 155 | 156 | ]) 157 | 158 | export default class Deutsch extends BaseLanguage { 159 | static abbreviations = abbreviations 160 | static MONTHS = new Set([ 161 | 'Januar', 162 | 'Februar', 163 | 'März', 164 | 'April', 165 | 'Mai', 166 | 'Juni', 167 | 'Juli', 168 | 'August', 169 | 'September', 170 | 'Oktober', 171 | 'November', 172 | 'Dezember' 173 | ]) 174 | 175 | continueInNextWord (textAfterBoundary) { 176 | if (textAfterBoundary.match(/^\W*[0-9a-z]/)) { 177 | return true 178 | } 179 | 180 | let nextWord = textAfterBoundary.trim().split(' ')[0] 181 | nextWord = nextWord.replace(/[?!.]/g, '') 182 | if (!nextWord.length) { 183 | return false 184 | } 185 | if (Deutsch.MONTHS.has(nextWord) || Deutsch.MONTHS.has(nextWord[0].toUpperCase() + nextWord.slice(1))) { 186 | return true 187 | } 188 | 189 | return false 190 | } 191 | 192 | isPunctuationBetweenQuotes () { 193 | return true 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /src/languages/es.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | 3 | const abbreviations = new Set([ 4 | 'a.c', 5 | 'a', 6 | 'a/c', 7 | 'abr', 8 | 'adj', 9 | 'admón', 10 | 'aero', 11 | 'afmo', 12 | 'ago', 13 | 'almte', 14 | 'ambi', 15 | 'an', 16 | 'anfi', 17 | 'ante', 18 | 'anti', 19 | 'ap', 20 | 'apdo', 21 | 'archi', 22 | 'arci', 23 | 'arq', 24 | 'art', 25 | 'atte', 26 | 'auto', 27 | 'av', 28 | 'avda', 29 | 'bco', 30 | 'bi', 31 | 'bibl', 32 | 'bien', 33 | 'bis', 34 | 'bs. as', 35 | 'c.f', 36 | 'c.g', 37 | 'c', 38 | 'c/c', 39 | 'c/u', 40 | 'cap', 41 | 'cc.aa', 42 | 'cdad', 43 | 'cm', 44 | 'co', 45 | 'com', 46 | 'con', 47 | 'contra', 48 | 'cra', 49 | 'crio', 50 | 'cta', 51 | 'cuadri', 52 | 'cuasi', 53 | 'cuatri', 54 | 'cv', 55 | 'd.e.p', 56 | 'da', 57 | 'dcha', 58 | 'dcho', 59 | 'de', 60 | 'deci', 61 | 'dep', 62 | 'des', 63 | 'di', 64 | 'dic', 65 | 'dicc', 66 | 'dir', 67 | 'dis', 68 | 'dn', 69 | 'doc', 70 | 'dom', 71 | 'dpto', 72 | 'dr', 73 | 'dra', 74 | 'dto', 75 | 'ecto', 76 | 'ee', 77 | 'ej', 78 | 'en', 79 | 'endo', 80 | 'entlo', 81 | 'entre', 82 | 'epi', 83 | 'equi', 84 | 'esq', 85 | 'etc', 86 | 'ex', 87 | 'excmo', 88 | 'ext', 89 | 'extra', 90 | 'f.c', 91 | 'fca', 92 | 'fdo', 93 | 'febr', 94 | 'ff. aa', 95 | 'ff.cc', 96 | 'fig', 97 | 'fil', 98 | 'fra', 99 | 'g.p', 100 | 'g/p', 101 | 'geo', 102 | 'gob', 103 | 'gr', 104 | 'gral', 105 | 'grs', 106 | 'hemi', 107 | 'hetero', 108 | 'hiper', 109 | 'hipo', 110 | 'hnos', 111 | 'homo', 112 | 'hs', 113 | 'i', 114 | 'igl', 115 | 'iltre', 116 | 'im', 117 | 'imp', 118 | 'impr', 119 | 'impto', 120 | 'in', 121 | 'incl', 122 | 'infra', 123 | 'ing', 124 | 'inst', 125 | 'inter', 126 | 'intra', 127 | 'iso', 128 | 'izdo', 129 | 'izq', 130 | 'izqdo', 131 | 'j.c', 132 | 'jue', 133 | 'jul', 134 | 'jun', 135 | 'kg', 136 | 'km', 137 | 'lcdo', 138 | 'ldo', 139 | 'let', 140 | 'lic', 141 | 'ltd', 142 | 'lun', 143 | 'macro', 144 | 'mar', 145 | 'máx', 146 | 'may', 147 | 'mega', 148 | 'mg', 149 | 'micro', 150 | 'mié', 151 | 'min', 152 | 'mín', 153 | 'mini', 154 | 'mm', 155 | 'mono', 156 | 'mt', 157 | 'multi', 158 | 'n. del t', 159 | 'n.b', 160 | 'neo', 161 | 'no', 162 | 'nos', 163 | 'nov', 164 | 'ntra. sra', 165 | 'núm', 166 | 'oct', 167 | 'omni', 168 | 'p.a', 169 | 'p.d', 170 | 'p.ej', 171 | 'p.v.p', 172 | 'p', 173 | 'pág', 174 | 'págs', 175 | 'para', 176 | 'párr', 177 | 'párrf', 178 | 'pen', 179 | 'ph.d', 180 | 'ph', 181 | 'pluri', 182 | 'poli', 183 | 'pos', 184 | 'post', 185 | 'pp', 186 | 'ppal', 187 | 'pre', 188 | 'prev', 189 | 'pro', 190 | 'prof', 191 | 'prov', 192 | 'pseudo', 193 | 'ptas', 194 | 'pts', 195 | 'pza', 196 | 'q.e.g.e', 197 | 'q.e.p.d', 198 | 'q.e.s.m', 199 | 're', 200 | 'reg', 201 | 'rep', 202 | 'retro', 203 | 'rr. hh', 204 | 'rte', 205 | 's. a', 206 | 's.a.r', 207 | 's.e', 208 | 's.l', 209 | 's.r.c', 210 | 's.r.l', 211 | 's.s.s', 212 | 's', 213 | 's/n', 214 | 'sáb', 215 | 'sdad', 216 | 'seg', 217 | 'semi', 218 | 'sept', 219 | 'seudo', 220 | 'sig', 221 | 'sobre', 222 | 'sr', 223 | 'sra', 224 | 'sres', 225 | 'srta', 226 | 'sta', 227 | 'sto', 228 | 'sub', 229 | 'super', 230 | 'supra', 231 | 't.v.e', 232 | 'tamb', 233 | 'tel', 234 | 'tfno', 235 | 'trans', 236 | 'tras', 237 | 'tri', 238 | 'ud', 239 | 'uds', 240 | 'ulter', 241 | 'ultra', 242 | 'un', 243 | 'uni', 244 | 'univ', 245 | 'uu', 246 | 'v.b', 247 | 'v.e', 248 | 'vd', 249 | 'vds', 250 | 'vice', 251 | 'vid', 252 | 'vie', 253 | 'vol', 254 | 'vs', 255 | 'vto', 256 | 'yuxta' 257 | ]) 258 | 259 | export default class Spanish extends BaseLanguage { 260 | static abbreviations = abbreviations 261 | } 262 | -------------------------------------------------------------------------------- /src/languages/sk.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | 3 | const MONTHS = new Set([ 4 | 'Január', 5 | 'Február', 6 | 'Marec', 7 | 'Apríl', 8 | 'Máj', 9 | 'Jún', 10 | 'Júl', 11 | 'August', 12 | 'September', 13 | 'Október', 14 | 'November', 15 | 'December', 16 | 'Januára', 17 | 'Februára', 18 | 'Marca', 19 | 'Apríla', 20 | 'Mája', 21 | 'Júna', 22 | 'Júla', 23 | 'Augusta', 24 | 'Septembra', 25 | 'Októbra', 26 | 'Novembra', 27 | 'Decembra' 28 | ]) 29 | 30 | const romanNumerals = 'i ii iii iv v vi vii viii ix x xi xii xiii xiv x xi xii xiii xv xvi xvii xviii xix xx' 31 | 32 | const romanNumeralsSet = new Set([...romanNumerals.split(' '), ...romanNumerals.toUpperCase().split(' ')]) 33 | 34 | const abbreviations = new Set([ 35 | ...romanNumeralsSet, 36 | 'a. d', 37 | 'a. g. p', 38 | 'a. i. i', 39 | 'a. k. a', 40 | 'a. m', 41 | 'a. r. k', 42 | 'a. s. a. p', 43 | 'a. s', 44 | 'a. v', 45 | 'a.d', 46 | 'a.g.p', 47 | 'a.i.i', 48 | 'a.k.a', 49 | 'a.m', 50 | 'a.s.a.p', 51 | 'a.s', 52 | 'a.v', 53 | 'akad', 54 | 'al', 55 | 'apod', 56 | 'arm', 57 | 'atď.', 58 | 'atd', 59 | 'atď', 60 | 'bc', 61 | 'bros', 62 | 'c. k', 63 | 'c.k', 64 | 'č', 65 | 'cca', 66 | 'co', 67 | 'corp', 68 | 'čs', 69 | 'csc', 70 | 'čsl', 71 | 'd. c', 72 | 'd.c', 73 | 'doc', 74 | 'dr', 75 | 'drsc', 76 | 'e. t', 77 | 'e.t', 78 | 'el', 79 | 'etc', 80 | 'ev', 81 | 'gen', 82 | 'hl', 83 | 'hod', 84 | 'i. b', 85 | 'i.b', 86 | 'ii', 87 | 'iii', 88 | 'inc', 89 | 'ind', 90 | 'ing', 91 | 'iv', 92 | 'jr', 93 | 'judr', 94 | 'k. o', 95 | 'k.o', 96 | 'kol', 97 | 'konkr', 98 | 'kt', 99 | 'll. m', 100 | 'll.m', 101 | 'ltd', 102 | 'm. n. m', 103 | 'm.n.m', 104 | 'm.o', 105 | 'max', 106 | 'mgr', 107 | 'mil', 108 | 'min', 109 | 'ml', 110 | 'mld', 111 | 'mr', 112 | 'mudr', 113 | 'mvdr', 114 | 'n. a', 115 | 'n. o', 116 | 'n. w. a', 117 | 'n.a', 118 | 'n.o', 119 | 'n.w.a', 120 | 'nám', 121 | 'napr', 122 | 'např', 123 | 'naprk', 124 | 'nár', 125 | 'nešp', 126 | 'no', 127 | 'nr', 128 | 'o. c. p', 129 | 'o. f. i', 130 | 'o. k', 131 | 'o. z', 132 | 'o.c.p', 133 | 'o.f.i', 134 | 'o.i', 135 | 'o.k', 136 | 'o.z', 137 | 'obr', 138 | 'obv', 139 | 'odd', 140 | 'ods', 141 | 'os', 142 | 'p. a', 143 | 'p. n. l', 144 | 'p. s', 145 | 'p.a', 146 | 'p.n.l', 147 | 'p.s', 148 | 'p', 149 | 'paeddr', 150 | 'pedg', 151 | 'ph. d', 152 | 'ph.d', 153 | 'phd', 154 | 'phdr', 155 | 'písm', 156 | 'plgr', 157 | 'pod', 158 | 'pok', 159 | 'pol. pr', 160 | 'pol.pr', 161 | 'por', 162 | 'pozn', 163 | 'pp', 164 | 'pr', 165 | 'prek', 166 | 'príp', 167 | 'prof', 168 | 'r. o', 169 | 'r.o', 170 | 'red', 171 | 'resp', 172 | 'rndr', 173 | 'roz', 174 | 'rozh', 175 | 'rsdr', 176 | 'rtg', 177 | 's. a', 178 | 's. e. g', 179 | 'š. p', 180 | 's. r. o', 181 | 's.a', 182 | 's.e.g', 183 | 'š.p', 184 | 's.r.o', 185 | 'skr', 186 | 'sl', 187 | 'slov', 188 | 'soc', 189 | 'sp', 190 | 'spol', 191 | 'sr', 192 | 'st', 193 | 'št', 194 | 'stor', 195 | 'str', 196 | 'stred', 197 | 'súkr', 198 | 'sv', 199 | 'sz', 200 | 't. č', 201 | 't. j', 202 | 't. z', 203 | 't.č', 204 | 't.j', 205 | 't.z', 206 | 'tel', 207 | 'tis', 208 | 'tj', 209 | 'tr', 210 | 'tu', 211 | 'tvz', 212 | 'tz', 213 | 'tzn', 214 | 'tzv', 215 | 'ú. p. v. o', 216 | 'u. s', 217 | 'ú.p.v.o', 218 | 'u.s', 219 | 'ul', 220 | 'v. sp', 221 | 'v.sp', 222 | 'var', 223 | 'vi', 224 | 'viď', 225 | 'vs', 226 | 'vyd', 227 | 'vz', 228 | 'xx', 229 | 'z. z', 230 | 'z.z', 231 | 'zák', 232 | 'zb', 233 | 'zdravot', 234 | 'zs', 235 | 'zz' 236 | ]) 237 | 238 | export default class Slovak extends BaseLanguage { 239 | static abbreviations = abbreviations 240 | 241 | continueInNextWord (textAfterBoundary) { 242 | if (textAfterBoundary.match(/^\W*[0-9a-z]/)) { 243 | return true 244 | } 245 | 246 | const nextWord = textAfterBoundary.trim().split(' ')[0] 247 | 248 | if (!nextWord.length) { 249 | return false 250 | } 251 | if (MONTHS.has(nextWord) || MONTHS.has(nextWord[0].toUpperCase() + nextWord.slice(1))) { 252 | return true 253 | } 254 | 255 | return false 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /src/languages/kk.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | 3 | const abbreviations = new Set([ 4 | 'afp', 5 | 'anp', 6 | 'atp', 7 | 'aбб', 8 | 'bae', 9 | 'bg', 10 | 'bp', 11 | 'cam', 12 | 'cctv', 13 | 'cd', 14 | 'cez', 15 | 'cgi', 16 | 'cnpc', 17 | 'dvd', 18 | 'eiti', 19 | 'epo', 20 | 'er', 21 | 'farc', 22 | 'fbi', 23 | 'gp', 24 | 'gps', 25 | 'has', 26 | 'hiv', 27 | 'hrh', 28 | 'http', 29 | 'icu', 30 | 'idf', 31 | 'imd', 32 | 'ime', 33 | 'ip', 34 | 'iso', 35 | 'kaz', 36 | 'kpa', 37 | 'kpo', 38 | 'kz', 39 | 'mgm', 40 | 'mri', 41 | 'nasa', 42 | 'nba', 43 | 'nbc', 44 | 'nds', 45 | 'ohl', 46 | 'omlt', 47 | 'pda', 48 | 'pkk', 49 | 'ppm', 50 | 'psm', 51 | 'psp', 52 | 'raf', 53 | 'rss', 54 | 'rtl', 55 | 'sas', 56 | 'sme', 57 | 'sms', 58 | 'tnt', 59 | 'udf', 60 | 'uefa', 61 | 'usb', 62 | 'utc', 63 | 'x', 64 | 'zdf', 65 | 'а.', 66 | 'аақ', 67 | 'авг.', 68 | 'аек', 69 | 'ак', 70 | 'акад.', 71 | 'акср', 72 | 'акцион.', 73 | 'ақ', 74 | 'ақш', 75 | 'амт', 76 | 'англ', 77 | 'аөсшк', 78 | 'апр.', 79 | 'апр', 80 | 'аум.', 81 | 'аф', 82 | 'ацат', 83 | 'әқбк', 84 | 'әөк', 85 | 'әч', 86 | 'б. з. б.', 87 | 'б. з. д.', 88 | 'б. т.', 89 | 'б. э. д.', 90 | 'б.б.', 91 | 'ббс', 92 | 'биікт.', 93 | 'биол.', 94 | 'биохим', 95 | 'бмтрк', 96 | 'боак', 97 | 'бө', 98 | 'бсн', 99 | 'бта', 100 | 'бұұ', 101 | 'бхооо', 102 | 'вич', 103 | 'всоонл', 104 | 'г', 105 | 'геогр.', 106 | 'геол.', 107 | 'гленкор', 108 | 'гсбп', 109 | 'гсдп', 110 | 'гулаг', 111 | 'гэс', 112 | 'ғ. с.', 113 | 'ғ.', 114 | 'дек.', 115 | 'дк', 116 | 'днқ', 117 | 'дсұ', 118 | 'еақк', 119 | 'еаэы', 120 | 'еқыұ', 121 | 'ембімұнайгаз', 122 | 'ео', 123 | 'еуразэқ', 124 | 'еуроодақ', 125 | 'еұу', 126 | 'еэы', 127 | 'ж.', 128 | 'жж.', 129 | 'жіө', 130 | 'жко', 131 | 'жкт', 132 | 'жққ', 133 | 'жоо', 134 | 'жсдп', 135 | 'жск', 136 | 'жтсх', 137 | 'жхл', 138 | 'жшс', 139 | 'жэк', 140 | 'зоо', 141 | 'и.', 142 | 'инта', 143 | 'исаф', 144 | 'іім', 145 | 'камаз', 146 | 'кг', 147 | 'кгб', 148 | 'кеу', 149 | 'кимеп', 150 | 'км', 151 | 'км²', 152 | 'км³', 153 | 'кмс', 154 | 'кокп', 155 | 'кота', 156 | 'кср', 157 | 'ксро', 158 | 'кту', 159 | 'кхдр', 160 | 'қ.', 161 | 'қазатомпром', 162 | 'қазкср', 163 | 'қазмұнайгаз', 164 | 'қазпошта', 165 | 'қазтаг', 166 | 'қазұу', 167 | 'қк', 168 | 'қкп', 169 | 'ққс', 170 | 'қмдб', 171 | 'қр', 172 | 'қхр', 173 | 'лат.', 174 | 'м.', 175 | 'м', 176 | 'м²', 177 | 'м³', 178 | 'магатэ', 179 | 'маж', 180 | 'май.', 181 | 'максам', 182 | 'мб', 183 | 'мбф', 184 | 'мвт', 185 | 'мемдум', 186 | 'мемл', 187 | 'мин', 188 | 'мқо', 189 | 'млн', 190 | 'млрд', 191 | 'мм.', 192 | 'мм', 193 | 'мр', 194 | 'мсоп', 195 | 'мт', 196 | 'мтк', 197 | 'мыс.', 198 | 'наса', 199 | 'нато', 200 | 'нквд', 201 | 'нояб.', 202 | 'нұсжп', 203 | 'оар', 204 | 'обб', 205 | 'обл.', 206 | 'огпу', 207 | 'оеб', 208 | 'окт.', 209 | 'оңт.', 210 | 'опек', 211 | 'өгк', 212 | 'өзенмұнайгаз', 213 | 'өұқ', 214 | 'өф', 215 | 'пәк', 216 | 'пед.', 217 | 'пиқ', 218 | 'р.', 219 | 'ржмб', 220 | 'ркфср', 221 | 'рлдп', 222 | 'рнқ', 223 | 'рсфср', 224 | 'ртж', 225 | 'руб', 226 | 'рф', 227 | 'рфкп', 228 | 'с.', 229 | 'с.ш.', 230 | 'сбд', 231 | 'сбл', 232 | 'свс', 233 | 'сву', 234 | 'сду', 235 | 'сент.', 236 | 'сес', 237 | 'см', 238 | 'снпс', 239 | 'солт.', 240 | 'сооно', 241 | 'спбму', 242 | 'сср', 243 | 'ссро', 244 | 'ссс', 245 | 'ссср', 246 | 'сэс', 247 | 'т. б.', 248 | 'т. с. с.', 249 | 'т.', 250 | 'т.с.с', 251 | 'т', 252 | 'тв', 253 | 'тереңд.', 254 | 'тех.', 255 | 'тж', 256 | 'тжқ', 257 | 'тим', 258 | 'тмд', 259 | 'төм.', 260 | 'тр', 261 | 'трлн', 262 | 'тэц', 263 | 'уаз', 264 | 'уефа', 265 | 'ук', 266 | 'ұқк', 267 | 'ұқшұ', 268 | 'февр.', 269 | 'фкққ', 270 | 'фққ', 271 | 'фсб', 272 | 'хвқ', 273 | 'хдо', 274 | 'хдп', 275 | 'хим.', 276 | 'хқко', 277 | 'хтқо', 278 | 'цас', 279 | 'цтп', 280 | 'ш.', 281 | 'ш.б.', 282 | 'шұар', 283 | 'шыұ', 284 | 'экон.', 285 | 'экспо', 286 | 'эқк', 287 | 'эөкк', 288 | 'эыдұ', 289 | 'юнеско', 290 | 'янв.', 291 | 'А', 292 | 'М', 293 | 'Т' 294 | ]) 295 | 296 | export default class Kazakh extends BaseLanguage { 297 | static abbreviations = abbreviations 298 | 299 | continueInNextWord (textAfterBoundary) { 300 | return textAfterBoundary.match(/^\W*[0-9a-zа-я]/) 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /test/ru.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 'Объем составляет 5 куб.м.': ['Объем составляет 5 куб.м.'], 6 | 'Маленькая девочка бежала и кричала: «Не видали маму?».': ['Маленькая девочка бежала и кричала: «Не видали маму?».'], 7 | 'Сегодня 27.10.14': ['Сегодня 27.10.14'], 8 | 9 | '«Я приду поздно», — сказал Андрей.': ['«Я приду поздно», — сказал Андрей.'], 10 | 11 | '«К чему ты готовишься? – спросила мама. – Завтра ведь выходной».': 12 | ['«К чему ты готовишься? – спросила мама. – Завтра ведь выходной».'], 13 | 14 | 'По словам Пушкина, «Привычка свыше дана, замена счастью она».': 15 | ['По словам Пушкина, «Привычка свыше дана, замена счастью она».'], 16 | 17 | 'Он сказал: «Я очень устал», и сразу же замолчал.': 18 | ['Он сказал: «Я очень устал», и сразу же замолчал.'], 19 | 20 | 'Мне стало как-то ужасно грустно в это мгновение; однако что-то похожее на смех зашевелилось в душе моей.': 21 | [ 22 | 'Мне стало как-то ужасно грустно в это мгновение; однако что-то похожее на смех зашевелилось в душе моей.' 23 | ], 24 | 'Шухов как был в ватных брюках, не снятых на ночь повыше левого колена их тоже был пришит затасканный, погрязневший лоскут, и на нем выведен черной, уже поблекшей краской номер Щ-854, надел телогрейку…': 25 | [ 26 | 'Шухов как был в ватных брюках, не снятых на ночь повыше левого колена их тоже был пришит затасканный, погрязневший лоскут, и на нем выведен черной, уже поблекшей краской номер Щ-854, надел телогрейку…' 27 | ], 28 | 29 | 'Слово «дом» является синонимом жилища': ['Слово «дом» является синонимом жилища'], 30 | 'В Санкт-Петербург на гастроли приехал театр «Современник»': 31 | ['В Санкт-Петербург на гастроли приехал театр «Современник»'], 32 | 33 | 'Машина едет со скоростью 100 км/ч.': ['Машина едет со скоростью 100 км/ч.'], 34 | 'Я поем и/или лягу спать.': ['Я поем и/или лягу спать.'], 35 | 'Он не мог справиться с примером "3 + (14:7) = 5"': ['Он не мог справиться с примером "3 + (14:7) = 5"'], 36 | 'Вот список: 1.мороженое, 2.мясо, 3.рис.': ['Вот список: 1.мороженое, 2.мясо, 3.рис.'], 37 | 'Квартира 234 находится на 4-ом этаже.': ['Квартира 234 находится на 4-ом этаже.'], 38 | 'В это время года температура может подниматься до 40°C.': ['В это время года температура может подниматься до 40°C.'], 39 | 40 | 'Объем составляет 5м³.': ['Объем составляет 5м³.'], 41 | 42 | 'Площадь комнаты 14м².': ['Площадь комнаты 14м².'], 43 | 'Площадь комнаты 14 кв.м.': ['Площадь комнаты 14 кв.м.'], 44 | '1°C соответствует 33.8°F.': ['1°C соответствует 33.8°F.'], 45 | 46 | 'Сегодня 27 октября 2014 года.': ['Сегодня 27 октября 2014 года.'], 47 | 'Эта машина стоит 150 000 дол.!': ['Эта машина стоит 150 000 дол.!'], 48 | 'Эта машина стоит $150 000!': ['Эта машина стоит $150 000!'], 49 | 'Вот номер моего телефона: +39045969798. Передавайте привет г-ну Шапочкину. До свидания.': [ 50 | 'Вот номер моего телефона: +39045969798.', 51 | 'Передавайте привет г-ну Шапочкину.', 52 | 'До свидания.' 53 | ], 54 | 55 | 'Постойте, разве можно указывать цены в у.е.!': ['Постойте, разве можно указывать цены в у.е.!'], 56 | 57 | 'Едем на скорости 90 км/ч в сторону пгт. Брагиновка, о котором мы так много слышали по ТВ!': [ 58 | 'Едем на скорости 90 км/ч в сторону пгт. Брагиновка, о котором мы так много слышали по ТВ!' 59 | ], 60 | 61 | 'Д-р ветеринарных наук А. И. Семенов и пр. выступали на этом семинаре.': 62 | ['Д-р ветеринарных наук А. И. Семенов и пр. выступали на этом семинаре.'], 63 | 64 | 'Уважаемый проф. Семенов! Просьба до 20.10 сдать отчет на кафедру.': 65 | ['Уважаемый проф. Семенов!', 'Просьба до 20.10 сдать отчет на кафедру.'], 66 | 67 | 'Первоначальная стоимость этого комплекта 30 долл., но сейчас действует скидка. Предъявите дисконтную карту, пожалуйста!': 68 | [ 69 | 'Первоначальная стоимость этого комплекта 30 долл., но сейчас действует скидка.', 70 | 'Предъявите дисконтную карту, пожалуйста!' 71 | ], 72 | 'Виктор съел пол-лимона и ушел по-английски из дома на ул. 1 Мая.': ['Виктор съел пол-лимона и ушел по-английски из дома на ул. 1 Мая.'], 73 | 'Напоминаю Вам, что 25.10 день рождения у Маши К., нужно будет купить ей подарок.': ['Напоминаю Вам, что 25.10 день рождения у Маши К., нужно будет купить ей подарок.'], 74 | 75 | 'В 2010-2012 гг. Виктор посещал г. Волгоград неоднократно.': ['В 2010-2012 гг. Виктор посещал г. Волгоград неоднократно.'], 76 | 77 | 'Маленькая девочка бежала и кричала: «Не видали маму?»': ['Маленькая девочка бежала и кричала: «Не видали маму?»'], 78 | 79 | 'Кв. 234 находится на 4 этаже.': ['Кв. 234 находится на 4 этаже.'], 80 | 81 | 'Нужно купить 1)рыбу 2)соль.': ['Нужно купить 1)рыбу 2)соль.'], 82 | 83 | 'Л.Н. Толстой написал "Войну и мир". Кроме Волконских, Л. Н. Толстой состоял в близком родстве с некоторыми другими аристократическими родами. Дом, где родился Л.Н.Толстой, 1898 г. В 1854 году дом продан по распоряжению писателя на вывоз в село Долгое.': [ 84 | 'Л.Н. Толстой написал "Войну и мир".', 85 | 'Кроме Волконских, Л. Н. Толстой состоял в близком родстве с некоторыми другими аристократическими родами.', 86 | 'Дом, где родился Л.Н.Толстой, 1898 г. В 1854 году дом продан по распоряжению писателя на вывоз в село Долгое.' 87 | ] 88 | 89 | } 90 | 91 | describe('Russian segment()', function () { 92 | for (const [text, expectedSentences] of Object.entries(tests)) { 93 | it(`correctly segments text: ${text}`, function () { 94 | const sentences = segment('ru', text) 95 | assert.deepEqual(sentences, expectedSentences) 96 | }) 97 | } 98 | }) 99 | -------------------------------------------------------------------------------- /src/fallbacks.json: -------------------------------------------------------------------------------- 1 | { 2 | "ab": ["ru"], 3 | "abs": ["id"], 4 | "ace": ["id"], 5 | "ady": ["ady-cyrl"], 6 | "aeb": ["aeb-arab"], 7 | "aeb-arab": ["ar"], 8 | "aln": ["sq"], 9 | "alt": ["ru"], 10 | "ami": ["zh-hant"], 11 | "an": ["es"], 12 | "anp": ["hi"], 13 | "arn": ["es"], 14 | "arq": ["ar"], 15 | "ary": ["ar"], 16 | "arz": ["ar"], 17 | "ast": ["es"], 18 | "atj": ["fr"], 19 | "av": ["ru"], 20 | "avk": ["fr", "es", "ru"], 21 | "awa": ["hi"], 22 | "ay": ["es"], 23 | "azb": ["fa"], 24 | "ba": ["ru"], 25 | "ban": ["id"], 26 | "ban-bali": ["ban"], 27 | "bar": ["de"], 28 | "bbc": ["bbc-latn"], 29 | "bbc-latn": ["id"], 30 | "bcc": ["fa"], 31 | "be-tarask": ["be"], 32 | "bgn": ["fa"], 33 | "bh": ["bho"], 34 | "bi": ["en"], 35 | "bjn": ["id"], 36 | "bm": ["fr"], 37 | "bpy": ["bn"], 38 | "bqi": ["fa"], 39 | "br": ["fr"], 40 | "btm": ["id"], 41 | "bug": ["id"], 42 | "bxr": ["ru"], 43 | "ca": ["oc"], 44 | "cbk-zam": ["es"], 45 | "cdo": ["nan", "zh-hant"], 46 | "ce": ["ru"], 47 | "co": ["it"], 48 | "crh": ["crh-latn"], 49 | "crh-cyrl": ["ru"], 50 | "cs": ["sk"], 51 | "csb": ["pl"], 52 | "cv": ["ru"], 53 | "de-at": ["de"], 54 | "de-ch": ["de"], 55 | "de-formal": ["de"], 56 | "dsb": ["de"], 57 | "dtp": ["ms"], 58 | "dty": ["ne"], 59 | "egl": ["it"], 60 | "eml": ["it"], 61 | "en-ca": ["en"], 62 | "en-gb": ["en"], 63 | "es-419": ["es"], 64 | "es-formal": ["es"], 65 | "ext": ["es"], 66 | "ff": ["fr"], 67 | "fit": ["fi"], 68 | "frc": ["fr"], 69 | "frp": ["fr"], 70 | "frr": ["de"], 71 | "fur": ["it"], 72 | "gag": ["tr"], 73 | "gan": ["gan-hant", "zh-hant", "zh-hans"], 74 | "gan-hans": ["zh-hans"], 75 | "gan-hant": ["zh-hant", "zh-hans"], 76 | "gcr": ["fr"], 77 | "gl": ["pt"], 78 | "glk": ["fa"], 79 | "gn": ["es"], 80 | "gom": ["gom-deva"], 81 | "gom-deva": ["hi"], 82 | "gor": ["id"], 83 | "gsw": ["de"], 84 | "guc": ["es"], 85 | "hak": ["zh-hant"], 86 | "hif": ["hif-latn"], 87 | "hrx": ["de"], 88 | "hsb": ["dsb", "de"], 89 | "ht": ["fr"], 90 | "hu-formal": ["hu"], 91 | "hyw": ["hy"], 92 | "ii": ["zh-cn", "zh-hans"], 93 | "inh": ["ru"], 94 | "io": ["eo"], 95 | "iu": ["ike-cans"], 96 | "jam": ["en"], 97 | "jut": ["da"], 98 | "jv": ["id"], 99 | "kaa": ["kk-latn", "kk-cyrl"], 100 | "kab": ["fr"], 101 | "kbd": ["kbd-cyrl"], 102 | "kbp": ["fr"], 103 | "khw": ["ur"], 104 | "kiu": ["tr"], 105 | "kjp": ["my"], 106 | "kk": ["kk-cyrl"], 107 | "kk-arab": ["kk-cyrl"], 108 | "kk-cn": ["kk-arab", "kk-cyrl"], 109 | "kk-kz": ["kk-cyrl"], 110 | "kk-latn": ["kk-cyrl"], 111 | "kk-tr": ["kk-latn", "kk-cyrl"], 112 | "kl": ["da"], 113 | "ko-kp": ["ko"], 114 | "koi": ["ru"], 115 | "krc": ["ru"], 116 | "krl": ["fi"], 117 | "ks": ["ks-arab"], 118 | "ksh": ["de"], 119 | "ku": ["ku-latn"], 120 | "ku-arab": ["ckb"], 121 | "kum": ["ru"], 122 | "kv": ["ru"], 123 | "lad": ["es"], 124 | "lb": ["de"], 125 | "lbe": ["ru"], 126 | "lez": ["ru", "az"], 127 | "li": ["nl"], 128 | "lij": ["it"], 129 | "liv": ["et"], 130 | "lki": ["fa"], 131 | "lld": ["it", "rm", "fur"], 132 | "lmo": ["pms", "eml", "lij", "vec", "it"], 133 | "ln": ["fr"], 134 | "lrc": ["fa"], 135 | "ltg": ["lv"], 136 | "luz": ["fa"], 137 | "lzh": ["zh-hant"], 138 | "lzz": ["tr"], 139 | "mad": ["id"], 140 | "mai": ["hi"], 141 | "map-bms": ["jv", "id"], 142 | "mdf": ["ru"], 143 | "mg": ["fr"], 144 | "mhr": ["ru"], 145 | "min": ["id"], 146 | "mnw": ["my"], 147 | "mo": ["ro"], 148 | "mrj": ["ru"], 149 | "ms-arab": ["ms"], 150 | "mwl": ["pt"], 151 | "myv": ["ru"], 152 | "mzn": ["fa"], 153 | "nah": ["es"], 154 | "nan": ["cdo", "zh-hant"], 155 | "nap": ["it"], 156 | "nds": ["de"], 157 | "nds-nl": ["nl"], 158 | "nia": ["id"], 159 | "nl-informal": ["nl"], 160 | "nn": ["nb"], 161 | "nrm": ["fr"], 162 | "oc": ["ca", "fr"], 163 | "olo": ["fi"], 164 | "os": ["ru"], 165 | "pcd": ["fr"], 166 | "pdc": ["de"], 167 | "pdt": ["de"], 168 | "pfl": ["de"], 169 | "pih": ["en"], 170 | "pms": ["it"], 171 | "pnt": ["el"], 172 | "pt": ["pt-br"], 173 | "pt-br": ["pt"], 174 | "qu": ["es"], 175 | "qug": ["es"], 176 | "rgn": ["it"], 177 | "rmy": ["ro"], 178 | "roa-tara": ["it"], 179 | "rue": ["uk", "ru"], 180 | "rup": ["ro"], 181 | "ruq": ["ruq-latn", "ro"], 182 | "ruq-cyrl": ["mk"], 183 | "ruq-latn": ["ro"], 184 | "sa": ["hi"], 185 | "sah": ["ru"], 186 | "scn": ["it"], 187 | "sco": ["en"], 188 | "sdc": ["it"], 189 | "sdh": ["cbk", "fa"], 190 | "ses": ["fr"], 191 | "sg": ["fr"], 192 | "sgs": ["lt"], 193 | "sh": ["bs", "sr-el", "hr"], 194 | "shi": ["fr"], 195 | "shy": ["shy-latn"], 196 | "shy-latn": ["fr"], 197 | "sk": ["cs"], 198 | "skr": ["skr-arab"], 199 | "skr-arab": ["ur", "pnb"], 200 | "sli": ["de"], 201 | "smn": ["fi"], 202 | "sr": ["sr-ec"], 203 | "srn": ["nl"], 204 | "stq": ["de"], 205 | "sty": ["ru"], 206 | "su": ["id"], 207 | "szl": ["pl"], 208 | "szy": ["zh-tw", "zh-hant", "zh-hans"], 209 | "tay": ["zh-tw", "zh-hant", "zh-hans"], 210 | "tcy": ["kn"], 211 | "tet": ["pt"], 212 | "tg": ["tg-cyrl"], 213 | "trv": ["zh-tw", "zh-hant", "zh-hans"], 214 | "tt": ["tt-cyrl", "ru"], 215 | "tt-cyrl": ["ru"], 216 | "ty": ["fr"], 217 | "tyv": ["ru"], 218 | "udm": ["ru"], 219 | "ug": ["ug-arab"], 220 | "vec": ["it"], 221 | "vep": ["et"], 222 | "vls": ["nl"], 223 | "vmf": ["de"], 224 | "vot": ["fi"], 225 | "vro": ["et"], 226 | "wa": ["fr"], 227 | "wo": ["fr"], 228 | "wuu": ["zh-hans"], 229 | "xal": ["ru"], 230 | "xmf": ["ka"], 231 | "yi": ["he"], 232 | "za": ["zh-hans"], 233 | "zea": ["nl"], 234 | "zgh": ["kab"], 235 | "zh": ["zh-hans"], 236 | "zh-cn": ["zh-hans"], 237 | "zh-hant": ["zh-hans"], 238 | "zh-hk": ["zh-hant", "zh-hans"], 239 | "zh-mo": ["zh-hk", "zh-hant", "zh-hans"], 240 | "zh-my": ["zh-sg", "zh-hans"], 241 | "zh-sg": ["zh-hans"], 242 | "zh-tw": ["zh-hant", "zh-hans"] 243 | } 244 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Sentencex demo 7 | 8 | 9 | 10 | 76 | 77 | 78 | 79 | 80 |
81 | 91 |
92 |
93 | Language: 94 | 95 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /src/base.js: -------------------------------------------------------------------------------- 1 | import GLOBAL_SENTENCE_TERMINATORS from './terminators.js' 2 | 3 | export default class Language { 4 | static GLOBAL_SENTENCE_BOUNDARY_REGEX = new RegExp( 5 | `[${GLOBAL_SENTENCE_TERMINATORS.join('')}]+`, 6 | 'gu' 7 | ) 8 | 9 | static EXCLAMATION_WORDS = new Set( 10 | ( 11 | '!Xũ !Kung ǃʼOǃKung !Xuun !Kung-Ekoka ǃHu ǃKhung ǃKu ǃung ǃXo ǃXû ǃXung ' + 12 | 'ǃXũ !Xun Yahoo! Y!J Yum!' 13 | ).split(' ') 14 | ) 15 | 16 | static quotePairs = { 17 | '"': '"', 18 | " '": "'", // Need a space before ' to avoid capturing don't , l'Avv etc 19 | '«': '»', 20 | '‘': '’', 21 | '‚': '‚', 22 | '“': '”', 23 | '‛': '‛', 24 | '„': '“', 25 | '‟': '‟', 26 | '‹': '›', 27 | '《': '》', 28 | '「': '」' 29 | } 30 | 31 | static quotesRegexStr = Object.entries(Language.quotePairs) 32 | .map(([left, right]) => `${left}(\\n|.)*?${right}`) 33 | .join('|') 34 | 35 | static quotesRegex = new RegExp(`${Language.quotesRegexStr}+`, 'g') 36 | 37 | static parensRegex = /([\\((<{\\[])(?:\\\1|.)*?[\\)\]})]/g 38 | static emailRegex = /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}/g 39 | 40 | static numberedReferenceRegex = /^(\[\d+])+/ 41 | static sentenceBreakRegex = Language.GLOBAL_SENTENCE_BOUNDARY_REGEX 42 | static abbreviationChar = '.' 43 | 44 | constructor () { 45 | this.abbreviations = this.constructor.abbreviations 46 | } 47 | 48 | is_abbreviation (head, tail, seperator) { 49 | // """ 50 | // Do not break in abbreviations. Example D. John, St. Peter 51 | // In the case of "This is Dr. Watson", head is "This is D/, tail is " Watson" 52 | // """ 53 | if (seperator !== this.constructor.abbreviationChar) { 54 | return false 55 | } 56 | 57 | const lastWord = this.get_lastword(head) 58 | if (!lastWord.length) { 59 | return false 60 | } 61 | 62 | const isAbbrev = 63 | this.abbreviations.has(lastWord) || 64 | this.abbreviations.has( 65 | lastWord[0].toLowerCase() + lastWord.slice(1) 66 | ) || 67 | this.abbreviations.has(lastWord.toUpperCase()) 68 | 69 | return isAbbrev 70 | } 71 | 72 | is_exclamation_word (head, tail) { 73 | return Language.EXCLAMATION_WORDS.has(this.get_lastword(head) + '!') 74 | } 75 | 76 | get_lastword (text) { 77 | return text.split(/[\s\\.]+/).slice(-1)[0] 78 | } 79 | 80 | findBoundary (text, match) { 81 | const tail = text.slice(match.index + 1) 82 | const head = text.slice(0, match.index) 83 | 84 | // If next word is numbered reference, expand boundary to that.' 85 | const numberRefMatch = Language.numberedReferenceRegex.exec(tail) 86 | 87 | if (numberRefMatch) { 88 | return match.index + 1 + numberRefMatch[0].length 89 | } 90 | 91 | // Next character is number or lower-case: not a sentence boundary 92 | if (this.continueInNextWord(tail)) { 93 | return null 94 | } 95 | 96 | const seperator = match[0] 97 | if (this.is_abbreviation(head, tail, seperator)) { 98 | return null 99 | } 100 | 101 | if (this.is_exclamation_word(head, tail)) { 102 | return null 103 | } 104 | 105 | // Include any closing punctuation and trailing space 106 | const matchLen = match[0].length 107 | // print(match_len) 108 | return match.index + matchLen 109 | } 110 | 111 | continueInNextWord (textAfterBoundary) { 112 | return textAfterBoundary.match(/^[0-9a-z]/) 113 | } 114 | 115 | getSkippableRanges (text) { 116 | const skippableRanges = [] 117 | 118 | // Find matches using quotesRegex and add spans to skippableRanges 119 | const quotesMatches = text.matchAll(this.constructor.quotesRegex) 120 | 121 | for (const match of quotesMatches) { 122 | skippableRanges.push([match.index, match.index + match[0].length]) 123 | } 124 | 125 | // Find matches using parensRegex and add spans to skippableRanges 126 | const parensMatches = text.matchAll(this.constructor.parensRegex) 127 | for (const match of parensMatches) { 128 | skippableRanges.push([match.index, match.index + match[0].length]) 129 | } 130 | 131 | // Find matches using emailRegex and add spans to skippableRanges 132 | const emailMatches = text.matchAll(this.constructor.emailRegex) 133 | for (const match of emailMatches) { 134 | skippableRanges.push([match.index, match.index + match[0].length]) 135 | } 136 | 137 | return skippableRanges 138 | } 139 | 140 | segment (text) { 141 | const paragraphs = text.split(/(\n{2,})/) 142 | const sentences = [] 143 | // Iterate over each paragraph. 144 | for (let i = 0; i < paragraphs.length; i++) { 145 | const paragraph = paragraphs[i] 146 | // Initialize a list to store the boundaries of sentences. 147 | const boundaries = [0] 148 | 149 | // Find all matches of sentence breaks in the paragraph. 150 | const matches = [] 151 | let match 152 | while ((match = this.constructor.sentenceBreakRegex.exec(paragraph)) !== null) { 153 | matches.push(match) 154 | } 155 | 156 | const skippableRanges = this.getSkippableRanges(paragraph) 157 | 158 | // Iterate over each match of sentence breaks. 159 | for (let j = 0; j < matches.length; j++) { 160 | const match = matches[j] 161 | // Find the boundary of the sentence. 162 | let boundary = this.findBoundary(paragraph, match) 163 | 164 | // If boundary is null, skip to the next match. 165 | if (!boundary) { 166 | continue 167 | } 168 | 169 | // Check if the boundary is inside a skippable range (quote, parentheses, or email). 170 | let inRange = false 171 | 172 | for (let sri = 0; sri < skippableRanges.length; sri++) { 173 | const [skipStart, skipEnd] = skippableRanges[sri] 174 | 175 | if (boundary > skipStart && boundary < skipEnd) { 176 | if (boundary + 1 === skipEnd && this.isPunctuationBetweenQuotes()) { 177 | boundary = skipEnd 178 | inRange = false 179 | } else { 180 | inRange = true 181 | } 182 | break 183 | } 184 | } 185 | // If in_range is True, skip to the next match. 186 | if (inRange) { 187 | continue 188 | } 189 | 190 | // Add the boundary to the boundaries list. 191 | boundaries.push(boundary) 192 | } 193 | 194 | for (let bindex = 0; bindex < boundaries.length; bindex++) { 195 | // Slice the paragraph using the boundaries to get the sentence. 196 | const sentence = paragraph.slice(boundaries[bindex], boundaries[bindex + 1]) 197 | 198 | // If the sentence has a length, yield the sentence 199 | // stripped of leading/trailing spaces. 200 | if (sentence.length) { 201 | sentences.push(sentence.replace(/^ +| +$/, '')) 202 | } 203 | } 204 | } 205 | return sentences 206 | } 207 | 208 | isPunctuationBetweenQuotes () { 209 | return false 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/languages/da.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | 3 | const abbreviations = new Set([ 4 | 'adm', 5 | 'adr', 6 | 'afd', 7 | 'afs', 8 | 'al', 9 | 'alm', 10 | 'ang', 11 | 'ank', 12 | 'anm', 13 | 'ann', 14 | 'ansvh', 15 | 'apr', 16 | 'årg', 17 | 'årh', 18 | 'årl', 19 | 'arr', 20 | 'ass', 21 | 'att', 22 | 'aud', 23 | 'aug', 24 | 'aut', 25 | 'bd', 26 | 'bdt', 27 | 'bet', 28 | 'bhk', 29 | 'bio', 30 | 'biol', 31 | 'bk', 32 | 'bl.a', 33 | 'bot', 34 | 'br', 35 | 'bto', 36 | 'ca', 37 | 'cal', 38 | 'cirk', 39 | 'cit', 40 | 'co', 41 | 'cpr-nr', 42 | 'cvr-nr', 43 | 'd.å', 44 | 'd.æ', 45 | 'd.d', 46 | 'd.e', 47 | 'd.m', 48 | 'd.s.s', 49 | 'd.s', 50 | 'd.y', 51 | 'da', 52 | 'dav', 53 | 'dec', 54 | 'def', 55 | 'del', 56 | 'dep', 57 | 'diam', 58 | 'din', 59 | 'dir', 60 | 'disp', 61 | 'distr', 62 | 'do', 63 | 'dobb', 64 | 'dr', 65 | 'ds', 66 | 'dvs', 67 | 'e.b', 68 | 'e.kr', 69 | 'e.l', 70 | 'e.o', 71 | 'e.v.t', 72 | 'eftf', 73 | 'eftm', 74 | 'egl', 75 | 'eks', 76 | 'eksam', 77 | 'ekskl', 78 | 'eksp', 79 | 'ekspl', 80 | 'el', 81 | 'emer', 82 | 'endv', 83 | 'eng', 84 | 'enk', 85 | 'etc', 86 | 'eur', 87 | 'evt', 88 | 'exam', 89 | 'f.å', 90 | 'f.eks', 91 | 'f.kr', 92 | 'f.m', 93 | 'f.n', 94 | 'f.o.m', 95 | 'f.o', 96 | 'f.s.v', 97 | 'f.t', 98 | 'f.v.t', 99 | 'f', 100 | 'fa', 101 | 'fær', 102 | 'fakt', 103 | 'feb', 104 | 'fec', 105 | 'ff', 106 | 'fg', 107 | 'fhv', 108 | 'fig', 109 | 'fl', 110 | 'flg', 111 | 'fm', 112 | 'fmd', 113 | 'forb', 114 | 'foreg', 115 | 'foren', 116 | 'forf', 117 | 'forh', 118 | 'fork', 119 | 'form', 120 | 'forr', 121 | 'fors', 122 | 'forsk', 123 | 'forts', 124 | 'fp', 125 | 'fr', 126 | 'frk', 127 | 'fru', 128 | 'fuldm', 129 | 'fung', 130 | 'fys', 131 | 'g.d', 132 | 'g.m', 133 | 'g', 134 | 'gd', 135 | 'gdr', 136 | 'gg', 137 | 'gh', 138 | 'gl', 139 | 'gn', 140 | 'gns', 141 | 'gr', 142 | 'grdl', 143 | 'gross', 144 | 'h.a', 145 | 'h.c', 146 | 'hdl', 147 | 'henh', 148 | 'henv', 149 | 'hf', 150 | 'hft', 151 | 'hhv', 152 | 'hort', 153 | 'hosp', 154 | 'hpl', 155 | 'hr', 156 | 'hrs', 157 | 'hum', 158 | 'i.e', 159 | 'i', 160 | 'ib', 161 | 'ibid', 162 | 'if', 163 | 'ifm', 164 | 'ill', 165 | 'indb', 166 | 'indreg', 167 | 'ing', 168 | 'inkl', 169 | 'insp', 170 | 'instr', 171 | 'isl', 172 | 'istf', 173 | 'jan', 174 | 'jf', 175 | 'jfr', 176 | 'jnr', 177 | 'jr', 178 | 'jul', 179 | 'jun', 180 | 'jur', 181 | 'jvf', 182 | 'kal', 183 | 'kap', 184 | 'kat', 185 | 'kbh', 186 | 'kem', 187 | 'kgl', 188 | 'kin', 189 | 'kl', 190 | 'kld', 191 | 'km/t', 192 | 'knsp', 193 | 'komm', 194 | 'kons', 195 | 'korr', 196 | 'kp', 197 | 'kr', 198 | 'kst', 199 | 'kt', 200 | 'ktr', 201 | 'kv', 202 | 'kvt', 203 | 'l.c', 204 | 'l', 205 | 'lab', 206 | 'lat', 207 | 'lb.', 208 | 'lb.nr', 209 | 'lb', 210 | 'lejl', 211 | 'lgd', 212 | 'lic', 213 | 'lign', 214 | 'lin', 215 | 'ling.merc', 216 | 'litt', 217 | 'lø', 218 | 'lok', 219 | 'lrs', 220 | 'ltr', 221 | 'm.a.o', 222 | 'm.fl.st', 223 | 'm.m', 224 | 'm', 225 | 'm/', 226 | 'ma', 227 | 'mag', 228 | 'maks', 229 | 'mar', 230 | 'mat', 231 | 'matr.nr', 232 | 'md', 233 | 'mdl', 234 | 'mdr', 235 | 'mdtl', 236 | 'med', 237 | 'medd', 238 | 'medflg', 239 | 'medl', 240 | 'merc', 241 | 'mezz', 242 | 'mf', 243 | 'mfl', 244 | 'mgl', 245 | 'mhp', 246 | 'mht', 247 | 'mi', 248 | 'mia', 249 | 'mio', 250 | 'ml', 251 | 'mods', 252 | 'modsv', 253 | 'modt', 254 | 'mr', 255 | 'mrk', 256 | 'mrs', 257 | 'ms', 258 | 'mul', 259 | 'mv', 260 | 'mvh', 261 | 'n.br', 262 | 'n.f', 263 | 'n', 264 | 'nat', 265 | 'ned', 266 | 'nedenn', 267 | 'nedenst', 268 | 'nederl', 269 | 'nkr', 270 | 'nl', 271 | 'no', 272 | 'nord', 273 | 'nov', 274 | 'nr', 275 | 'nto', 276 | 'nuv', 277 | 'o.a', 278 | 'ø.f', 279 | 'o.fl.st', 280 | 'o.g', 281 | 'o.h', 282 | 'o.m.a', 283 | 'o', 284 | 'obj', 285 | 'obl', 286 | 'obs', 287 | 'odont', 288 | 'oecon', 289 | 'off', 290 | 'ofl', 291 | 'okt', 292 | 'omg', 293 | 'omr', 294 | 'omtr', 295 | 'on', 296 | 'op.cit', 297 | 'opg', 298 | 'opl', 299 | 'opr', 300 | 'org', 301 | 'orig', 302 | 'osfr', 303 | 'osv', 304 | 'øv', 305 | 'ovenn', 306 | 'ovenst', 307 | 'overs', 308 | 'ovf', 309 | 'øvr', 310 | 'oz', 311 | 'p.a', 312 | 'p.b.v', 313 | 'p.c', 314 | 'p.m.v', 315 | 'p.p', 316 | 'p.s', 317 | 'p.t', 318 | 'p.v.a', 319 | 'p.v.c', 320 | 'p', 321 | 'pæd', 322 | 'par', 323 | 'partc', 324 | 'pass', 325 | 'pct', 326 | 'pd', 327 | 'pens', 328 | 'perf', 329 | 'pers', 330 | 'pg', 331 | 'pga', 332 | 'pgl', 333 | 'ph.d', 334 | 'ph', 335 | 'pharm', 336 | 'phil', 337 | 'pinx', 338 | 'pk', 339 | 'pkt', 340 | 'pl', 341 | 'pluskv', 342 | 'polit', 343 | 'polyt', 344 | 'port', 345 | 'pos', 346 | 'pp', 347 | 'pr', 348 | 'præd', 349 | 'præf', 350 | 'præp', 351 | 'præs', 352 | 'præt', 353 | 'prc', 354 | 'priv', 355 | 'prod', 356 | 'prof', 357 | 'pron', 358 | 'psych', 359 | 'pt', 360 | 'q.e.d', 361 | 'rad', 362 | 'red', 363 | 'ref', 364 | 'reg', 365 | 'regn', 366 | 'rel', 367 | 'rep', 368 | 'repr', 369 | 'rest', 370 | 'rk', 371 | 'russ', 372 | 's.å', 373 | 's.br', 374 | 's.d', 375 | 's.e', 376 | 's.f', 377 | 's.m.b.a', 378 | 's.u', 379 | 's', 380 | 's/', 381 | 'sa', 382 | 'sædv', 383 | 'såk', 384 | 'sb', 385 | 'sc', 386 | 'scient', 387 | 'sek', 388 | 'sekr', 389 | 'sem', 390 | 'sen', 391 | 'sep', 392 | 'sept', 393 | 'sg', 394 | 'sign', 395 | 'sj', 396 | 'skr', 397 | 'skt', 398 | 'slutn', 399 | 'sml', 400 | 'smp', 401 | 'sms', 402 | 'smst', 403 | 'sø', 404 | 'soc', 405 | 'sort', 406 | 'sp', 407 | 'spec', 408 | 'spm', 409 | 'spr', 410 | 'spsk', 411 | 'st', 412 | 'stk', 413 | 'str', 414 | 'stud', 415 | 'subj', 416 | 'subst', 417 | 'suff', 418 | 'sup', 419 | 'suppl', 420 | 'sv', 421 | 't.h', 422 | 't.o.m', 423 | 't.v', 424 | 't', 425 | 'tab', 426 | 'td', 427 | 'tdl', 428 | 'tdr', 429 | 'techn', 430 | 'tekn', 431 | 'temp', 432 | 'th', 433 | 'ti', 434 | 'tidl', 435 | 'tilf', 436 | 'tilh', 437 | 'till', 438 | 'tilsv', 439 | 'tjg', 440 | 'tlf', 441 | 'tlgr', 442 | 'to', 443 | 'tr', 444 | 'trp', 445 | 'tv', 446 | 'ty', 447 | 'u.å', 448 | 'u.p', 449 | 'u.st', 450 | 'u', 451 | 'uafh', 452 | 'ubf', 453 | 'ubøj', 454 | 'udb', 455 | 'udbet', 456 | 'udd', 457 | 'udg', 458 | 'uds', 459 | 'ugtl', 460 | 'ulin', 461 | 'ult', 462 | 'undt', 463 | 'univ', 464 | 'v.f', 465 | 'vær', 466 | 'var', 467 | 'vb', 468 | 'vbsb', 469 | 'vedk', 470 | 'vedl', 471 | 'vedr', 472 | 'vejl', 473 | 'vh', 474 | 'vol', 475 | 'vs', 476 | 'vsa', 477 | 'zool' 478 | ]) 479 | 480 | export default class Danish extends BaseLanguage { 481 | static abbreviations = abbreviations 482 | 483 | continueInNextWord (textAfterBoundary) { 484 | return textAfterBoundary.match(/^\W*[0-9a-z]/) 485 | } 486 | } 487 | -------------------------------------------------------------------------------- /test/es.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | '¿Cómo está hoy? Espero que muy bien.': ['¿Cómo está hoy?', 'Espero que muy bien.'], 6 | '¡Hola señorita! Espero que muy bien.': ['¡Hola señorita!', 'Espero que muy bien.'], 7 | 'Hola Srta. Ledesma. Buenos días, soy el Lic. Naser Pastoriza, y él es mi padre, el Dr. Naser.': [ 8 | 'Hola Srta. Ledesma.', 9 | 'Buenos días, soy el Lic. Naser Pastoriza, y él es mi padre, el Dr. Naser.' 10 | ], 11 | 12 | '¡La casa cuesta $170.500.000,00! ¡Muy costosa! Se prevé una disminución del 12.5% para el próximo año.': 13 | [ 14 | '¡La casa cuesta $170.500.000,00!', 15 | '¡Muy costosa!', 16 | 'Se prevé una disminución del 12.5% para el próximo año.' 17 | ], 18 | 19 | '«Ninguna mente extraordinaria está exenta de un toque de demencia.», dijo Aristóteles.': ['«Ninguna mente extraordinaria está exenta de un toque de demencia.», dijo Aristóteles.'], 20 | 21 | '«Ninguna mente extraordinaria está exenta de un toque de demencia», dijo Aristóteles. Pablo, ¿adónde vas? ¡¿Qué viste?!': 22 | [ 23 | '«Ninguna mente extraordinaria está exenta de un toque de demencia», dijo Aristóteles.', 24 | 'Pablo, ¿adónde vas?', 25 | '¡¿Qué viste?!' 26 | ], 27 | 28 | 'Admón. es administración o me equivoco.': ['Admón. es administración o me equivoco.'], 29 | '¡Hola Srta. Ledesma! ¿Cómo está hoy? Espero que muy bien.': 30 | ['¡Hola Srta. Ledesma!', '¿Cómo está hoy?', 'Espero que muy bien.'], 31 | 32 | 'Buenos días, soy el Lic. Naser Pastoriza, y él es mi padre, el Dr. Naser.': 33 | ['Buenos días, soy el Lic. Naser Pastoriza, y él es mi padre, el Dr. Naser.'], 34 | 35 | 'He apuntado una cita para la siguiente fecha: Mar. 23 de Nov. de 2014. Gracias.': 36 | ['He apuntado una cita para la siguiente fecha: Mar. 23 de Nov. de 2014.', 'Gracias.'], 37 | 38 | 'Núm. de tel: 351.123.465.4. Envíe mis saludos a la Sra. Rescia.': 39 | ['Núm. de tel: 351.123.465.4.', 'Envíe mis saludos a la Sra. Rescia.'], 40 | 41 | 'Cero en la escala Celsius o de grados centígrados 0 °C se define como el equivalente a 273.15 K, con una diferencia de temperatura de 1 °C equivalente a una diferencia de 1 Kelvin. Esto significa que 100 °C, definido como el punto de ebullición del agua, se define como el equivalente a 373.15 K.': 42 | [ 43 | 'Cero en la escala Celsius o de grados centígrados 0 °C se define como el equivalente a 273.15 K, con una diferencia de temperatura de 1 °C equivalente a una diferencia de 1 Kelvin.', 44 | 'Esto significa que 100 °C, definido como el punto de ebullición del agua, se define como el equivalente a 373.15 K.' 45 | ], 46 | 47 | 'Durante la primera misión del Discovery 30 Ago. 1984 15:08.10 tuvo lugar el lanzamiento de dos satélites de comunicación, el nombre de esta misión fue STS-41-D.': [ 48 | 'Durante la primera misión del Discovery 30 Ago. 1984 15:08.10 tuvo lugar el lanzamiento de dos satélites de comunicación, el nombre de esta misión fue STS-41-D.' 49 | ], 50 | 51 | 'Frase del gran José Hernández: "Aquí me pongo a cantar / al compás de la vigüela, / que el hombre que lo desvela / una pena estrordinaria, / como la ave solitaria / con el cantar se consuela. / [...] ".': [ 52 | 'Frase del gran José Hernández: "Aquí me pongo a cantar / al compás de la vigüela, / que el hombre que lo desvela / una pena estrordinaria, / como la ave solitaria / con el cantar se consuela. / [...] ".' 53 | ], 54 | 55 | 'Citando a Criss Jami «Prefiero ser un artista a ser un líder, irónicamente, un líder tiene que seguir las reglas.», lo cual parece muy acertado.': 56 | [ 57 | 'Citando a Criss Jami «Prefiero ser un artista a ser un líder, irónicamente, un líder tiene que seguir las reglas.», lo cual parece muy acertado.' 58 | ], 59 | 60 | 'Cuando llegué, le estaba dando ejercicios a los niños, uno de los cuales era "3 + 14/7.x = 5". ¿Qué te parece?': 61 | [ 62 | 'Cuando llegué, le estaba dando ejercicios a los niños, uno de los cuales era "3 + 14/7.x = 5".', 63 | '¿Qué te parece?' 64 | ], 65 | 66 | // pytest.param 67 | // "Se le pidió a los niños que leyeran los párrf. 5 y 6 del art. 4 de la constitución de los EE. UU..": 68 | // [ 69 | // "Se le pidió a los niños que leyeran los párrf. 5 y 6 del art. 4 de la constitución de los EE. UU.." 70 | // ], 71 | // marks=pytest.mark.xfail, 72 | 73 | 'Una de las preguntas realizadas en la evaluación del día Lun. 15 de Mar. fue la siguiente: "Alumnos, ¿cuál es el resultado de la operación 1.1 + 4/5?". Disponían de 1 min. para responder esa pregunta.': [ 74 | 'Una de las preguntas realizadas en la evaluación del día Lun. 15 de Mar. fue la siguiente: "Alumnos, ¿cuál es el resultado de la operación 1.1 + 4/5?".', 75 | 'Disponían de 1 min. para responder esa pregunta.' 76 | ], 77 | 78 | 'La temperatura del motor alcanzó los 120.5°C. Afortunadamente, pudo llegar al final de carrera.': [ 79 | 'La temperatura del motor alcanzó los 120.5°C.', 80 | 'Afortunadamente, pudo llegar al final de carrera.' 81 | ], 82 | 83 | 'El volumen del cuerpo es 3m³. ¿Cuál es la superficie de cada cara del prisma?': ['El volumen del cuerpo es 3m³.', '¿Cuál es la superficie de cada cara del prisma?'], 84 | 85 | 'La habitación tiene 20.55m². El living tiene 50.0m².': ['La habitación tiene 20.55m².', 'El living tiene 50.0m².'], 86 | 87 | '1°C corresponde a 33.8°F. ¿A cuánto corresponde 35°C?': ['1°C corresponde a 33.8°F.', '¿A cuánto corresponde 35°C?'], 88 | 89 | 'Hamilton ganó el último gran premio de Fórmula 1, luego de 1:39:02.619 Hs. de carrera, segundo resultó Massa, a una diferencia de 2.5 segundos. De esta manera se consagró ¡Campeón mundial!': [ 90 | 'Hamilton ganó el último gran premio de Fórmula 1, luego de 1:39:02.619 Hs. de carrera, segundo resultó Massa, a una diferencia de 2.5 segundos.', 91 | 'De esta manera se consagró ¡Campeón mundial!' 92 | ], 93 | 94 | 'El corredor No. 103 arrivó 4°.': ['El corredor No. 103 arrivó 4°.'], 95 | 96 | 'Hoy es 27/04/2014, y es mi cumpleaños. ¿Cuándo es el tuyo?': ['Hoy es 27/04/2014, y es mi cumpleaños.', '¿Cuándo es el tuyo?'], 97 | 98 | // pytest.param 99 | // "Aquí está la lista de compras para el almuerzo: 1.Helado, 2.Carne, 3.Arroz. ¿Cuánto costará? Quizás $12.5.": 100 | // [ 101 | // "Aquí está la lista de compras para el almuerzo: 1.Helado, 2.Carne, 3.Arroz.", 102 | // "¿Cuánto costará?", 103 | // "Quizás $12.5.", 104 | // ], 105 | // marks=pytest.mark.xfail, 106 | 107 | '1 + 1 es 2. 2 + 2 es 4. El auto es de color rojo.': ['1 + 1 es 2.', '2 + 2 es 4.', 'El auto es de color rojo.'], 108 | 109 | 'La máquina viajaba a 100 km/h. ¿En cuánto tiempo recorrió los 153 Km.?': ['La máquina viajaba a 100 km/h.', '¿En cuánto tiempo recorrió los 153 Km.?'], 110 | 111 | 'Explora oportunidades de carrera en el área de Salud en el Hospital de Northern en Mt. Kisco.': [ 112 | 'Explora oportunidades de carrera en el área de Salud en el Hospital de Northern en Mt. Kisco.' 113 | ] 114 | 115 | } 116 | 117 | describe('Spanish segment()', function () { 118 | for (const [text, expectedSentences] of Object.entries(tests)) { 119 | it(`correctly segments text: ${text}`, function () { 120 | const sentences = segment('es', text) 121 | assert.deepEqual(sentences, expectedSentences) 122 | }) 123 | } 124 | }) 125 | -------------------------------------------------------------------------------- /test/hy.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 'Ի՞նչ ես մտածում: Ոչինչ:': ['Ի՞նչ ես մտածում:', 'Ոչինչ:'], 6 | 7 | 'Ապրիլի 24-ին սկսեց անձրևել...Այդպես էի գիտեի:': ['Ապրիլի 24-ին սկսեց անձրևել...Այդպես էի գիտեի:'], 8 | 9 | 'Այսպիսով` մոտենում ենք ավարտին: Տրամաբանությյունը հետևյալն է. պարզություն և աշխատանք:': [ 10 | 'Այսպիսով` մոտենում ենք ավարտին:', 11 | 'Տրամաբանությյունը հետևյալն է. պարզություն և աշխատանք:' 12 | ], 13 | 14 | 'Սա այն փուլն է, երբ տեղի է ունենում Համակարգի մշակումը: Համաձայն Փուլ 2-ի, Մատակարարը մշակում և/կամ հարմարեցնում է համապատասխան ծրագիրը, տեղադրում ծրագրի բաղկացուցիչները, կատարում առանձին բլոկի և համակարգի թեստավորում և ներառում տարբեր մոդուլներ եզակի աշխատանքային համակարգում, որը կազմում է այս Փուլի արդյունքը:': [ 15 | 'Սա այն փուլն է, երբ տեղի է ունենում Համակարգի մշակումը:', 16 | 'Համաձայն Փուլ 2-ի, Մատակարարը մշակում և/կամ հարմարեցնում է համապատասխան ծրագիրը, տեղադրում ծրագրի բաղկացուցիչները, կատարում առանձին բլոկի և համակարգի թեստավորում և ներառում տարբեր մոդուլներ եզակի աշխատանքային համակարգում, որը կազմում է այս Փուլի արդյունքը:' 17 | ], 18 | 19 | 'Մատակարարի նախագծի անձնակազմի կողմից համակարգի թեստերը հաջող անցնելուց հետո, Համակարգը տրվում է Գնորդին թեստավորման համար: 2-րդ փուլում, հիմք ընդունելով թեստային սցենարիոները, թեստերը կատարվում են Կառավարության կողմից Մատակարարի աջակցությամբ: Այս թեստերի թիրախը հանդիսանում է Համակարգի` որպես մեկ ամբողջության և համակարգի գործունեության ստուգումը համաձայն տեխնիկական բնութագրերի: Այս թեստերի հաջողակ ավարտից հետո, Համակարգը ժամանակավոր ընդունվում է Կառավարության կողմից: Այս թեստերի արդյունքները փաստաթղթային ձևով կներակայացվեն Թեստային Արդյունքների Հաշվետվություններում: Մատակարարը պետք է տրամադրի հետևյալը`': 20 | [ 21 | 'Մատակարարի նախագծի անձնակազմի կողմից համակարգի թեստերը հաջող անցնելուց հետո, Համակարգը տրվում է Գնորդին թեստավորման համար:', 22 | '2-րդ փուլում, հիմք ընդունելով թեստային սցենարիոները, թեստերը կատարվում են Կառավարության կողմից Մատակարարի աջակցությամբ:', 23 | 'Այս թեստերի թիրախը հանդիսանում է Համակարգի` որպես մեկ ամբողջության և համակարգի գործունեության ստուգումը համաձայն տեխնիկական բնութագրերի:', 24 | 'Այս թեստերի հաջողակ ավարտից հետո, Համակարգը ժամանակավոր ընդունվում է Կառավարության կողմից:', 25 | 'Այս թեստերի արդյունքները փաստաթղթային ձևով կներակայացվեն Թեստային Արդյունքների Հաշվետվություններում:', 26 | 'Մատակարարը պետք է տրամադրի հետևյալը`' 27 | ], 28 | 29 | // "Hello world. My name is Armine." ==> ["Hello world.", "My name is Armine."] 30 | 'Բարև Ձեզ: Իմ անունն էԱրմինե:': ['Բարև Ձեզ:', 'Իմ անունն էԱրմինե:'], 31 | // "Today is Monday. I am going to work." ==> ["Today is Monday.", "I am going to work."] 32 | 33 | 'Այսօր երկուշաբթի է: Ես գնում եմ աշխատանքի:': ['Այսօր երկուշաբթի է:', 'Ես գնում եմ աշխատանքի:'], 34 | 35 | // "Tomorrow is September 1st. We are going to school." ==> ["Tomorrow is September 1st.", "We are going to school."] 36 | 37 | 'Վաղը սեպտեմբերի 1-ն է: Մենք գնում ենք դպրոց:': ['Վաղը սեպտեմբերի 1-ն է:', 'Մենք գնում ենք դպրոց:'], 38 | 39 | // "Yes, I understood. I really love you." ==> ["Yes, I understood.", "I really love you."] 40 | 41 | 'Այո, ես հասկացա: Ես իսկապես քեզ սիրում եմ:': 42 | ['Այո, ես հասկացա:', 'Ես իսկապես քեզ սիրում եմ:'], 43 | 44 | // "Close the windows. It is raining in the evening." ==> ["Close the windows.", "It is raining in the evening."] 45 | 'Փակիր պատուհանները: Երեկոյան անձրևում է:': ['Փակիր պատուհանները:', 'Երեկոյան անձրևում է:'], 46 | // "It is dark. I should go home." ==> ["It is dark.", "I should go home."] 47 | 'Մութ է: Ես պետք է տուն վերադառնամ:': ['Մութ է:', 'Ես պետք է տուն վերադառնամ:'], 48 | // "You know, I am starting to believe. Everything is changing." ==> ["You know, I am starting to believe.", "Everything is changing."] 49 | 50 | 'Գիտես, սկսել եմ հավատալ: Ամեն ինչ փոխվում է:': ['Գիտես, սկսել եմ հավատալ:', 'Ամեն ինչ փոխվում է:'], 51 | 52 | // "It is a new Christmas tree. We should decorate it." ==> ["It is a new Christmas tree.", "We should decorate it."] 53 | 'Տոնածառը նոր է: Պետք է այն զարդարել:': ['Տոնածառը նոր է:', 'Պետք է այն զարդարել:'], 54 | // "I am in hurry. I could not wait you." ==> ["I am in hurry.", "I could not wait you."] 55 | 'Ես շտապում եմ: Ես քեզ չեմ կարող սպասել:': ['Ես շտապում եմ:', 'Ես քեզ չեմ կարող սպասել:'], 56 | // "Wait, we love each other. I want us to live together." ==> ["Wait, we love each other.", "I want us to live together."] 57 | 58 | 'Սպասիր, մենք իրար սիրում ենք: Ցանկանում եմ միասին ապրենք:': ['Սպասիր, մենք իրար սիրում ենք:', 'Ցանկանում եմ միասին ապրենք:'], 59 | 60 | // "No, I do not think so. It is not true." ==> ["No, I do not think so.", "It is not true."] 61 | 'Ոչ, այդպես չեմ կարծում: Դա ճիշտ չէ:': ['Ոչ, այդպես չեմ կարծում:', 'Դա ճիշտ չէ:'], 62 | 63 | // "It was 1960...it was winter...it was night. It was cold...emptiness." ==> ["It was 1960...it was winter...it was night.", "It was cold...emptiness."] 64 | 65 | '1960 թվական…ձմեռ…գիշեր: Սառն էր…դատարկություն:': 66 | ['1960 թվական…ձմեռ…գիշեր:', 'Սառն էր…դատարկություն:'], 67 | 68 | // "Why a computer could not do what a man could do? Simply it doesn't have a human brain." ==> ["Why a computer could not do what a man could do?", "Simply it doesn't have a human brain."] 69 | 70 | 'Ինչ՟ու այն, ինչ անում է մարդը, չի կարող անել համակարգիչը: Պարզապես չունի մարդկային ուղեղ:': 71 | [ 72 | 'Ինչ՟ու այն, ինչ անում է մարդը, չի կարող անել համակարգիչը:', 73 | 'Պարզապես չունի մարդկային ուղեղ:' 74 | ], 75 | 76 | // "Numerate for me 3 things that are important for you - I answer love, knowledge, sincerity." ==> ["Numerate for me 3 things that are important for you - I answer love, knowledge, sincerity."] 77 | 78 | 'Թվարկիր ինձ համար 3 բան, որ կարևոր է քեզ համար - Պատասխանում եմ. սեր, գիտելիք, ազնվություն:': 79 | [ 80 | 'Թվարկիր ինձ համար 3 բան, որ կարևոր է քեզ համար - Պատասխանում եմ. սեր, գիտելիք, ազնվություն:' 81 | ], 82 | 83 | // "So, we are coming to the end. The logic is...simplicity and work" ==> ["So, we are coming to the end.", "Simplicity and work."] 84 | 85 | // "Can we work together ?. May be what you are thinking, is possible." ==> ["Can we work together?.", "May be what you are thinking is possible."] 86 | 87 | 'Կարող ե՞նք միասին աշխատել: Գուցե այն ինչ մտածում ես, իրականանալի է:': 88 | ['Կարող ե՞նք միասին աշխատել:', 'Գուցե այն ինչ մտածում ես, իրականանալի է:'], 89 | 90 | // "Now what we have started, comes to the end. However the questions are numerous... ." ==> ["Now what we have started, comes to the end.", "However the questions are numerous... ."] 91 | 92 | 'Հիմա, այն ինչ սկսել ենք, ավարտին է մոտենում: Հարցերը սակայն շատ են...:': 93 | ['Հիմա, այն ինչ սկսել ենք, ավարտին է մոտենում:', 'Հարցերը սակայն շատ են...:'], 94 | 95 | // "Honey... I am waiting. Shall I go... or?" ==> ["Honey... I am waiting.", "Shall I go... or?"] 96 | 'Սիրելիս...սպասում եմ: Գնամ թ՟ե …:': ['Սիրելիս...սպասում եմ:', 'Գնամ թ՟ե …:'], 97 | 'Դիեգո Արմանդո Մարադոնան ծնվել է 1960 թվականի հոկտեմբերի 30-ին (կիրակի)` առավոտյան ժամը 5-ին, Բուենոս-Այրես գավառում գտնվող Լանուս քաղաքի Էվիտա կլինիկայում: Նա ծնվել է Դոն Դիեգոյի ընտանիքում: Հայրն աշխատում էր Տրիտումոլ հողմաղացում որպես բանվոր, իսկ մայրը` Դալմա Սալվադորա Ֆրանկոն, տնային տնտեսուհի էր։ Դիեգոն ընտանիքի հինգերորդ, բայց առաջին արու զավակն էր, ուներ չորս քույր` Ռիտան, Աննան, Էլզան և Մարիան։ Դալմա Սալվադորան ասում էր. «Նա բոլորովին չչարչարեց ինձ. շաբաթ ամբողջ օրը ես ինձ շատ լավ էի զգում, իսկ գիշերն ինձ կլինիկա տարան: Նա շատ արագ լույս աշխարհ եկավ: Այդ պահին ես միայն մի բան էի խնդրում. որպեսզի նա առողջ ծնվի և լավ մարդ դառնա: Բարեբախտաբար, այդ ամենն իրականացավ, կարծում եմ, դեռ մի բան էլ ավելի»։': [ 98 | 'Դիեգո Արմանդո Մարադոնան ծնվել է 1960 թվականի հոկտեմբերի 30-ին (կիրակի)` առավոտյան ժամը 5-ին, Բուենոս-Այրես գավառում գտնվող Լանուս քաղաքի Էվիտա կլինիկայում:', 99 | 'Նա ծնվել է Դոն Դիեգոյի ընտանիքում:', 100 | 'Հայրն աշխատում էր Տրիտումոլ հողմաղացում որպես բանվոր, իսկ մայրը` Դալմա Սալվադորա Ֆրանկոն, տնային տնտեսուհի էր։', 101 | 'Դիեգոն ընտանիքի հինգերորդ, բայց առաջին արու զավակն էր, ուներ չորս քույր` Ռիտան, Աննան, Էլզան և Մարիան։', 102 | 'Դալմա Սալվադորան ասում էր. «Նա բոլորովին չչարչարեց ինձ. շաբաթ ամբողջ օրը ես ինձ շատ լավ էի զգում, իսկ գիշերն ինձ կլինիկա տարան: Նա շատ արագ լույս աշխարհ եկավ: Այդ պահին ես միայն մի բան էի խնդրում. որպեսզի նա առողջ ծնվի և լավ մարդ դառնա: Բարեբախտաբար, այդ ամենն իրականացավ, կարծում եմ, դեռ մի բան էլ ավելի»։' 103 | ] 104 | } 105 | 106 | describe('Armenian segment()', function () { 107 | for (const [text, expectedSentences] of Object.entries(tests)) { 108 | it(`correctly segments text: ${text}`, function () { 109 | const sentences = segment('hy', text) 110 | assert.deepEqual(sentences, expectedSentences) 111 | }) 112 | } 113 | }) 114 | -------------------------------------------------------------------------------- /test/en.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 'This is Dr. Watson': ['This is Dr. Watson'], 6 | 'Roses Are Red. Violets Are Blue': ['Roses Are Red.', 'Violets Are Blue'], 7 | 'Hello! How are you?': ['Hello!', 'How are you?'], 8 | 'This is a test.': ['This is a test.'], 9 | 'Mr. Smith went to Washington.': ['Mr. Smith went to Washington.'], 10 | 'What a suprise?!': ['What a suprise?!'], 11 | "That's all folks...": ["That's all folks..."], 12 | 'First line\nSecond line': ['First line\nSecond line'], 13 | 'First line\nSecond line\n\nThird line': [ 14 | 'First line\nSecond line', 15 | '\n\n', 16 | 'Third line' 17 | ], 18 | 19 | 'This is UK. Not US': ['This is UK.', 'Not US'], 20 | 'This balloon costs $1.20': ['This balloon costs $1.20'], 21 | 'Hello World. My name is Jonas.': ['Hello World.', 'My name is Jonas.'], 22 | 'What is your name? My name is Jonas.': ['What is your name?', 'My name is Jonas.'], 23 | 'There it is! I found it.': ['There it is!', 'I found it.'], 24 | 'My name is Jonas E. Smith.': ['My name is Jonas E. Smith.'], 25 | 'Please turn to p. 55.': ['Please turn to p. 55.'], 26 | 'Were Jane and co. at the party?': ['Were Jane and co. at the party?'], 27 | 'They closed the deal with Pitt, Briggs & Co. at noon.': ['They closed the deal with Pitt, Briggs & Co. at noon.'], 28 | 29 | // pytest.param( 30 | // "Let's ask Jane and co. They should know.", 31 | // # Ideal result 32 | // ["Let's ask Jane and co.", "They should know."], 33 | // # Acceptable: 34 | // # ["Let's ask Jane and co. They should know."], 35 | // marks=pytest.mark.xfail, 36 | // , 37 | // pytest.param( 38 | // "They closed the deal with Pitt, Briggs & Co. It closed yesterday.", 39 | // # Ideal result 40 | // [ 41 | // "They closed the deal with Pitt, Briggs & Co.", 42 | // "It closed yesterday.", 43 | // ], 44 | // # Acceptable: 45 | // # ["They closed the deal with Pitt, Briggs & Co. It closed yesterday."], 46 | // marks=pytest.mark.xfail, 47 | // , 48 | 'I can see Mt. Fuji from here.': ['I can see Mt. Fuji from here.'], 49 | 50 | "St. Michael's Church is on 5th st. near the light.": ["St. Michael's Church is on 5th st. near the light."], 51 | 52 | "That is JFK Jr.'s book.": ["That is JFK Jr.'s book."], 53 | 'I visited the U.S.A. last year.': ['I visited the U.S.A. last year.'], 54 | // pytest.param( 55 | // "I live in the E.U. How about you?", 56 | // ["I live in the E.U.", "How about you?"], 57 | // marks=pytest.mark.xfail, 58 | // , 59 | // pytest.param( 60 | // "I live in the U.S. How about you?", 61 | // ["I live in the U.S.", "How about you?"], 62 | // marks=pytest.mark.xfail, 63 | // , 64 | 65 | 'I work for the U.S. Government in Virginia.': ['I work for the U.S. Government in Virginia.'], 66 | 67 | 'I have lived in the U.S. for 20 years.': ['I have lived in the U.S. for 20 years.'], 68 | // Most difficult sentence to crack 69 | // pytest.param( 70 | // "At 5 a.m. Mr. Smith went to the bank. \ 71 | // He left the bank at 6 P.M. Mr. Smith then went to the store.", 72 | // # Ideal result: 73 | // [ 74 | // "At 5 a.m. Mr. Smith went to the bank.", 75 | // "He left the bank at 6 P.M.", 76 | // "Mr. Smith then went to the store.", 77 | // ], 78 | // # Acceptable: 79 | // # [ 80 | // # "At 5 a.m. Mr. Smith went to the bank.", 81 | // # "He left the bank at 6 P.M. Mr. Smith then went to the store.", 82 | // # ], 83 | // marks=pytest.mark.xfail, 84 | // , 85 | 'She has $100.00 in her bag.': ['She has $100.00 in her bag.'], 86 | 'She has $100.00. It is in her bag.': ['She has $100.00.', 'It is in her bag.'], 87 | 88 | 'He teaches science (He previously worked for 5 years as an engineer.) at the local University.': [ 89 | 'He teaches science (He previously worked for 5 years as an engineer.) at the local University.' 90 | ], 91 | 92 | 'Her email is Jane.Doe@example.com. I sent her an email.': [ 93 | 'Her email is Jane.Doe@example.com.', 94 | 'I sent her an email.' 95 | ], 96 | 97 | 'The site is, https,//www.example.50.com/new-site/awesome_content.html. Please check it out.': [ 98 | 'The site is, https,//www.example.50.com/new-site/awesome_content.html.', 99 | 'Please check it out.' 100 | ], 101 | 102 | "She turned to him, 'This is great.' she said.": ["She turned to him, 'This is great.' she said."], 103 | 104 | 'She turned to him, "This is great." she said.': ['She turned to him, "This is great." she said.'], 105 | 106 | // pytest.param( 107 | // 'She turned to him, "This is great." She held the book out to show him.', 108 | // [ 109 | // 'She turned to him, "This is great."', 110 | // "She held the book out to show him.", 111 | // ], 112 | // marks=pytest.mark.xfail, 113 | 114 | 'Hello!! Long time no see.': ['Hello!!', 'Long time no see.'], 115 | 'Hello?? Who is there?': ['Hello??', 'Who is there?'], 116 | 'Hello!? Is that you?': ['Hello!?', 'Is that you?'], 117 | 'Hello?! Is that you?': ['Hello?!', 'Is that you?'], 118 | // # Lists are not supported now 119 | // # "1.) The first item 2.) The second item": ["1.) The first item", "2.) The second item"], 120 | // # "1.) The first item. 2.) The second item.": ["1.) The first item.", "2.) The second item."], 121 | // # "1) The first item 2) The second item": ["1) The first item", "2) The second item"], 122 | // # "1) The first item. 2) The second item.": ["1) The first item.", "2) The second item."], 123 | // # "1. The first item 2. The second item": ["1. The first item", "2. The second item"], 124 | // # "1. The first item. 2. The second item.": ["1. The first item.", "2. The second item."], 125 | // # ( 126 | // # "• 9. The first item • 10. The second item", 127 | // # [ 128 | // # "• 9. The first item", 129 | // # "• 10. The second item", 130 | // # ], 131 | // # , 132 | // # "⁃9. The first item ⁃10. The second item": ["⁃9. The first item", "⁃10. The second item"], 133 | // # ( 134 | // # "a. The first item b. The second item c. The third list item", 135 | // # [ 136 | // # "a. The first item", 137 | // # "b. The second item", 138 | // # "c. The third list item", 139 | // # ], 140 | // # , 141 | 142 | 'You can find it at N°. 1026.253.553. That is where the treasure is.': [ 143 | 'You can find it at N°. 1026.253.553.', 144 | 'That is where the treasure is.' 145 | ], 146 | 147 | 'She works at Yahoo! in the accounting department.': ['She works at Yahoo! in the accounting department.'], 148 | 149 | // pytest.param( 150 | // "We make a good team, you and I. Did you see Albert I. Jones yesterday?", 151 | // [ 152 | // "We make a good team, you and I.", 153 | // "Did you see Albert I. Jones yesterday?", 154 | // ], 155 | // marks=pytest.mark.xfail, 156 | 157 | 'Thoreau argues that by simplifying one’s life, “the laws of the universe will appear less complex. . . .”': [ 158 | 'Thoreau argues that by simplifying one’s life, “the laws of the universe will appear less complex. . . .”' 159 | ], 160 | 161 | '"Bohr [...] used the analogy of parallel stairways [...]" (Smith 55).': ['"Bohr [...] used the analogy of parallel stairways [...]" (Smith 55).'], 162 | 163 | // pytest.param( 164 | // "If words are left off at the end of a sentence, and that is all that is omitted, indicate the omission with ellipsis marks (preceded and followed by a space) and then indicate the end of the sentence with a period . . . . Next sentence.", 165 | // [ 166 | // "If words are left off at the end of a sentence, and that is all that is omitted, indicate the omission with ellipsis marks (preceded and followed by a space) and then indicate the end of the sentence with a period . . . .", 167 | // "Next sentence.", 168 | // ], 169 | // marks=pytest.mark.xfail, 170 | 171 | 'I never meant that.... She left the store.': [ 172 | 'I never meant that....', 173 | 'She left the store.' 174 | ], 175 | 176 | // pytest.param( 177 | // "I wasn’t really ... well, what I mean...see . . . what I'm saying, the thing is . . . I didn’t mean it.", 178 | // [ 179 | // "I wasn’t really ... well, what I mean...see . . . what I'm saying, the thing is . . . I didn’t mean it." 180 | // ], 181 | // marks=pytest.mark.xfail, 182 | 183 | // pytest.param( 184 | // "One further habit which was somewhat weakened . . . was that of combining words into self-interpreting compounds. . . . The practice was not abandoned. . . .", 185 | // [ 186 | // "One further habit which was somewhat weakened . . . was that of combining words into self-interpreting compounds.", 187 | // ". . . The practice was not abandoned. . . .", 188 | // ], 189 | // marks=pytest.mark.xfail, 190 | 191 | 'Saint Maximus (died 250) is a Christian saint and martyr.[1] The emperor Decius published a decree ordering the veneration of busts of the deified emperors.': [ 192 | 'Saint Maximus (died 250) is a Christian saint and martyr.[1]', 193 | 'The emperor Decius published a decree ordering the veneration of busts of the deified emperors.' 194 | ], 195 | 196 | 'Differing agendas can potentially create an understanding gap in a consultation.11 12 Take the example of one of the most common presentations in ill health: the common cold.': [ 197 | 'Differing agendas can potentially create an understanding gap in a consultation.11 12 Take the example of one of the most common presentations in ill health: the common cold.' 198 | ], 199 | 200 | 'Its traditional use[1] is well documented in the ethnobotanical literature [2–11]. Leaves, buds, tar and essential oils are used to treat a wide spectrum of diseases.': [ 201 | 'Its traditional use[1] is well documented in the ethnobotanical literature [2–11].', 202 | 'Leaves, buds, tar and essential oils are used to treat a wide spectrum of diseases.' 203 | ], 204 | 205 | "Thus increasing the desire for political reform both in Lancashire and in the country at large.[7][8] This was a serious misdemeanour,[16] encouraging them to declare the assembly illegal as soon as it was announced on 31 July.[17][18] The radicals sought a second opinion on the meeting's legality.": [ 206 | 'Thus increasing the desire for political reform both in Lancashire and in the country at large.[7][8]', 207 | 'This was a serious misdemeanour,[16] encouraging them to declare the assembly illegal as soon as it was announced on 31 July.[17][18]', 208 | "The radicals sought a second opinion on the meeting's legality." 209 | ], 210 | 211 | '“Why, indeed?” murmured Holmes. “Your Majesty had not spoken before I \nwas aware that I was addressing Wilhelm Gottsreich Sigismond von \nOrmstein, Grand Duke of Cassel-Felstein, and hereditary King of \nBohemia.”': [ 212 | '“Why, indeed?” murmured Holmes.', 213 | '“Your Majesty had not spoken before I \nwas aware that I was addressing Wilhelm Gottsreich Sigismond von \nOrmstein, Grand Duke of Cassel-Felstein, and hereditary King of \nBohemia.”' 214 | ], 215 | 216 | '“How many? I don’t know.”': ['“How many? I don’t know.”'] 217 | 218 | } 219 | 220 | // Check for spurious matching of unpaired surrogate in RegExp character class. This can happen 221 | // because a sentence terminator above U+FFFF is represented as two Javascript characters, 222 | // and so putting it into a RegExp character class will match either surrogate separately. 223 | // For example, U+1BC9F (Duployan Punctuation Chinook Full Stop) is represented as 224 | // '\uD82F\uDC9F', but a character class [\uD82F\uDC9F] will match other characters such as 225 | // U+1BC00 (represented as '\uD82F\uDC00'). 226 | // Test contributed by David Chan 227 | const lettersAboveFFFF = String.fromCodePoint(0x1BC00).repeat(10) 228 | tests[lettersAboveFFFF] = [lettersAboveFFFF] 229 | 230 | describe('English segment()', function () { 231 | for (const [text, expectedSentences] of Object.entries(tests)) { 232 | it(`correctly segments text: ${text}`, function () { 233 | const sentences = segment('en', text) 234 | assert.deepEqual(sentences, expectedSentences) 235 | }) 236 | } 237 | }) 238 | -------------------------------------------------------------------------------- /src/terminators.js: -------------------------------------------------------------------------------- 1 | // unicode code points generated with Unicode::Tussle perl script: 2 | // unichars -aBbs '[\p{Sentence_Break=STerm}\p{Sentence_Break=ATerm}]' | awk '$2="\""$2"\", //"' 3 | // Refer: https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/SentenceBreakProperty.txt 4 | const GLOBAL_SENTENCE_TERMINATORS = [ 5 | '!', // U+00021 BC=ON BLK=Basic_Latin SC=Common EXCLAMATION MARK 6 | '.', // U+0002E BC=CS BLK=Basic_Latin SC=Common FULL STOP 7 | '?', // U+0003F BC=ON BLK=Basic_Latin SC=Common QUESTION MARK 8 | '։', // U+00589 BC=L BLK=Armenian SC=Armenian ARMENIAN FULL STOP 9 | '؝', // U+0061D BC=AL BLK=Arabic SC=Arabic ARABIC END OF TEXT MARK 10 | '؞', // U+0061E BC=AL BLK=Arabic SC=Arabic ARABIC TRIPLE DOT PUNCTUATION MARK 11 | '؟', // U+0061F BC=AL BLK=Arabic SC=Common ARABIC QUESTION MARK 12 | '۔', // U+006D4 BC=AL BLK=Arabic SC=Arabic ARABIC FULL STOP 13 | '܀', // U+00700 BC=AL BLK=Syriac SC=Syriac SYRIAC END OF PARAGRAPH 14 | '܁', // U+00701 BC=AL BLK=Syriac SC=Syriac SYRIAC SUPRALINEAR FULL STOP 15 | '܂', // U+00702 BC=AL BLK=Syriac SC=Syriac SYRIAC SUBLINEAR FULL STOP 16 | '߹', // U+007F9 BC=ON BLK=NKo SC=Nko NKO EXCLAMATION MARK 17 | '࠷', // U+00837 BC=R BLK=Samaritan SC=Samaritan SAMARITAN PUNCTUATION MELODIC QITSA 18 | '࠹', // U+00839 BC=R BLK=Samaritan SC=Samaritan SAMARITAN PUNCTUATION QITSA 19 | '࠽', // U+0083D BC=R BLK=Samaritan SC=Samaritan SAMARITAN PUNCTUATION SOF MASHFAAT 20 | '࠾', // U+0083E BC=R BLK=Samaritan SC=Samaritan SAMARITAN PUNCTUATION ANNAAU 21 | '।', // U+00964 BC=L BLK=Devanagari SC=Common DEVANAGARI DANDA 22 | '॥', // U+00965 BC=L BLK=Devanagari SC=Common DEVANAGARI DOUBLE DANDA 23 | '၊', // U+0104A BC=L BLK=Myanmar SC=Myanmar MYANMAR SIGN LITTLE SECTION 24 | '။', // U+0104B BC=L BLK=Myanmar SC=Myanmar MYANMAR SIGN SECTION 25 | '።', // U+01362 BC=L BLK=Ethiopic SC=Ethiopic ETHIOPIC FULL STOP 26 | '፧', // U+01367 BC=L BLK=Ethiopic SC=Ethiopic ETHIOPIC QUESTION MARK 27 | '፨', // U+01368 BC=L BLK=Ethiopic SC=Ethiopic ETHIOPIC PARAGRAPH SEPARATOR 28 | '᙮', // U+0166E BC=L BLK=Unified_Canadian_Aboriginal_Syllabics SC=Canadian_Aboriginal CANADIAN SYLLABICS FULL STOP 29 | '᜵', // U+01735 BC=L BLK=Hanunoo SC=Common PHILIPPINE SINGLE PUNCTUATION 30 | '᜶', // U+01736 BC=L BLK=Hanunoo SC=Common PHILIPPINE DOUBLE PUNCTUATION 31 | '᠃', // U+01803 BC=ON BLK=Mongolian SC=Common MONGOLIAN FULL STOP 32 | '᠉', // U+01809 BC=ON BLK=Mongolian SC=Mongolian MONGOLIAN MANCHU FULL STOP 33 | '᥄', // U+01944 BC=ON BLK=Limbu SC=Limbu LIMBU EXCLAMATION MARK 34 | '᥅', // U+01945 BC=ON BLK=Limbu SC=Limbu LIMBU QUESTION MARK 35 | '᪨', // U+01AA8 BC=L BLK=Tai_Tham SC=Tai_Tham TAI THAM SIGN KAAN 36 | '᪩', // U+01AA9 BC=L BLK=Tai_Tham SC=Tai_Tham TAI THAM SIGN KAANKUU 37 | '᪪', // U+01AAA BC=L BLK=Tai_Tham SC=Tai_Tham TAI THAM SIGN SATKAAN 38 | '᪫', // U+01AAB BC=L BLK=Tai_Tham SC=Tai_Tham TAI THAM SIGN SATKAANKUU 39 | '᭚', // U+01B5A BC=L BLK=Balinese SC=Balinese BALINESE PANTI 40 | '᭛', // U+01B5B BC=L BLK=Balinese SC=Balinese BALINESE PAMADA 41 | '᭞', // U+01B5E BC=L BLK=Balinese SC=Balinese BALINESE CARIK SIKI 42 | '᭟', // U+01B5F BC=L BLK=Balinese SC=Balinese BALINESE CARIK PAREREN 43 | '᭽', // U+01B7D BC=L BLK=Balinese SC=Balinese BALINESE PANTI LANTANG 44 | '᭾', // U+01B7E BC=L BLK=Balinese SC=Balinese BALINESE PAMADA LANTANG 45 | '᰻', // U+01C3B BC=L BLK=Lepcha SC=Lepcha LEPCHA PUNCTUATION TA-ROL 46 | '᰼', // U+01C3C BC=L BLK=Lepcha SC=Lepcha LEPCHA PUNCTUATION NYET THYOOM TA-ROL 47 | '᱾', // U+01C7E BC=L BLK=Ol_Chiki SC=Ol_Chiki OL CHIKI PUNCTUATION MUCAAD 48 | '᱿', // U+01C7F BC=L BLK=Ol_Chiki SC=Ol_Chiki OL CHIKI PUNCTUATION DOUBLE MUCAAD 49 | '․', // U+02024 BC=ON BLK=General_Punctuation SC=Common ONE DOT LEADER 50 | '‼', // U+0203C BC=ON BLK=General_Punctuation SC=Common DOUBLE EXCLAMATION MARK 51 | '‽', // U+0203D BC=ON BLK=General_Punctuation SC=Common INTERROBANG 52 | '⁇', // U+02047 BC=ON BLK=General_Punctuation SC=Common DOUBLE QUESTION MARK 53 | '⁈', // U+02048 BC=ON BLK=General_Punctuation SC=Common QUESTION EXCLAMATION MARK 54 | '⁉', // U+02049 BC=ON BLK=General_Punctuation SC=Common EXCLAMATION QUESTION MARK 55 | '⸮', // U+02E2E BC=ON BLK=Supplemental_Punctuation SC=Common REVERSED QUESTION MARK 56 | '⸼', // U+02E3C BC=ON BLK=Supplemental_Punctuation SC=Common STENOGRAPHIC FULL STOP 57 | '⹓', // U+02E53 BC=ON BLK=Supplemental_Punctuation SC=Common MEDIEVAL EXCLAMATION MARK 58 | '⹔', // U+02E54 BC=ON BLK=Supplemental_Punctuation SC=Common MEDIEVAL QUESTION MARK 59 | '꓿', // U+0A4FF BC=L BLK=Lisu SC=Lisu LISU PUNCTUATION FULL STOP 60 | '꘎', // U+0A60E BC=ON BLK=Vai SC=Vai VAI FULL STOP 61 | '꘏', // U+0A60F BC=ON BLK=Vai SC=Vai VAI QUESTION MARK 62 | '꛳', // U+0A6F3 BC=L BLK=Bamum SC=Bamum BAMUM FULL STOP 63 | '꛷', // U+0A6F7 BC=L BLK=Bamum SC=Bamum BAMUM QUESTION MARK 64 | '꡶', // U+0A876 BC=ON BLK=Phags-pa SC=Phags_Pa PHAGS-PA MARK SHAD 65 | '꡷', // U+0A877 BC=ON BLK=Phags-pa SC=Phags_Pa PHAGS-PA MARK DOUBLE SHAD 66 | '꣎', // U+0A8CE BC=L BLK=Saurashtra SC=Saurashtra SAURASHTRA DANDA 67 | '꣏', // U+0A8CF BC=L BLK=Saurashtra SC=Saurashtra SAURASHTRA DOUBLE DANDA 68 | '꤯', // U+0A92F BC=L BLK=Kayah_Li SC=Kayah_Li KAYAH LI SIGN SHYA 69 | '꧈', // U+0A9C8 BC=L BLK=Javanese SC=Javanese JAVANESE PADA LINGSA 70 | '꧉', // U+0A9C9 BC=L BLK=Javanese SC=Javanese JAVANESE PADA LUNGSI 71 | '꩝', // U+0AA5D BC=L BLK=Cham SC=Cham CHAM PUNCTUATION DANDA 72 | '꩞', // U+0AA5E BC=L BLK=Cham SC=Cham CHAM PUNCTUATION DOUBLE DANDA 73 | '꩟', // U+0AA5F BC=L BLK=Cham SC=Cham CHAM PUNCTUATION TRIPLE DANDA 74 | '꫰', // U+0AAF0 BC=L BLK=Meetei_Mayek_Extensions SC=Meetei_Mayek MEETEI MAYEK CHEIKHAN 75 | '꫱', // U+0AAF1 BC=L BLK=Meetei_Mayek_Extensions SC=Meetei_Mayek MEETEI MAYEK AHANG KHUDAM 76 | '꯫', // U+0ABEB BC=L BLK=Meetei_Mayek SC=Meetei_Mayek MEETEI MAYEK CHEIKHEI 77 | '﹒', // U+0FE52 BC=CS BLK=Small_Form_Variants SC=Common SMALL FULL STOP 78 | '﹖', // U+0FE56 BC=ON BLK=Small_Form_Variants SC=Common SMALL QUESTION MARK 79 | '﹗', // U+0FE57 BC=ON BLK=Small_Form_Variants SC=Common SMALL EXCLAMATION MARK 80 | '!', // U+0FF01 BC=ON BLK=Halfwidth_and_Fullwidth_Forms SC=Common FULLWIDTH EXCLAMATION MARK 81 | '.', // U+0FF0E BC=CS BLK=Halfwidth_and_Fullwidth_Forms SC=Common FULLWIDTH FULL STOP 82 | '?', // U+0FF1F BC=ON BLK=Halfwidth_and_Fullwidth_Forms SC=Common FULLWIDTH QUESTION MARK 83 | '𐩖', // U+10A56 BC=R BLK=Kharoshthi SC=Kharoshthi KHAROSHTHI PUNCTUATION DANDA 84 | '𐩗', // U+10A57 BC=R BLK=Kharoshthi SC=Kharoshthi KHAROSHTHI PUNCTUATION DOUBLE DANDA 85 | '𐽕', // U+10F55 BC=AL BLK=Sogdian SC=Sogdian SOGDIAN PUNCTUATION TWO VERTICAL BARS 86 | '𐽖', // U+10F56 BC=AL BLK=Sogdian SC=Sogdian SOGDIAN PUNCTUATION TWO VERTICAL BARS WITH DOTS 87 | '𐽗', // U+10F57 BC=AL BLK=Sogdian SC=Sogdian SOGDIAN PUNCTUATION CIRCLE WITH DOT 88 | '𐽘', // U+10F58 BC=AL BLK=Sogdian SC=Sogdian SOGDIAN PUNCTUATION TWO CIRCLES WITH DOTS 89 | '𐽙', // U+10F59 BC=AL BLK=Sogdian SC=Sogdian SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT 90 | '𐾆', // U+10F86 BC=R BLK=Old_Uyghur SC=Old_Uyghur OLD UYGHUR PUNCTUATION BAR 91 | '𐾇', // U+10F87 BC=R BLK=Old_Uyghur SC=Old_Uyghur OLD UYGHUR PUNCTUATION TWO BARS 92 | '𐾈', // U+10F88 BC=R BLK=Old_Uyghur SC=Old_Uyghur OLD UYGHUR PUNCTUATION TWO DOTS 93 | '𐾉', // U+10F89 BC=R BLK=Old_Uyghur SC=Old_Uyghur OLD UYGHUR PUNCTUATION FOUR DOTS 94 | '𑁇', // U+11047 BC=L BLK=Brahmi SC=Brahmi BRAHMI DANDA 95 | '𑁈', // U+11048 BC=L BLK=Brahmi SC=Brahmi BRAHMI DOUBLE DANDA 96 | '𑂾', // U+110BE BC=L BLK=Kaithi SC=Kaithi KAITHI SECTION MARK 97 | '𑂿', // U+110BF BC=L BLK=Kaithi SC=Kaithi KAITHI DOUBLE SECTION MARK 98 | '𑃀', // U+110C0 BC=L BLK=Kaithi SC=Kaithi KAITHI DANDA 99 | '𑃁', // U+110C1 BC=L BLK=Kaithi SC=Kaithi KAITHI DOUBLE DANDA 100 | '𑅁', // U+11141 BC=L BLK=Chakma SC=Chakma CHAKMA DANDA 101 | '𑅂', // U+11142 BC=L BLK=Chakma SC=Chakma CHAKMA DOUBLE DANDA 102 | '𑅃', // U+11143 BC=L BLK=Chakma SC=Chakma CHAKMA QUESTION MARK 103 | '𑇅', // U+111C5 BC=L BLK=Sharada SC=Sharada SHARADA DANDA 104 | '𑇆', // U+111C6 BC=L BLK=Sharada SC=Sharada SHARADA DOUBLE DANDA 105 | '𑇍', // U+111CD BC=L BLK=Sharada SC=Sharada SHARADA SUTRA MARK 106 | '𑇞', // U+111DE BC=L BLK=Sharada SC=Sharada SHARADA SECTION MARK-1 107 | '𑇟', // U+111DF BC=L BLK=Sharada SC=Sharada SHARADA SECTION MARK-2 108 | '𑈸', // U+11238 BC=L BLK=Khojki SC=Khojki KHOJKI DANDA 109 | '𑈹', // U+11239 BC=L BLK=Khojki SC=Khojki KHOJKI DOUBLE DANDA 110 | '𑈻', // U+1123B BC=L BLK=Khojki SC=Khojki KHOJKI SECTION MARK 111 | '𑈼', // U+1123C BC=L BLK=Khojki SC=Khojki KHOJKI DOUBLE SECTION MARK 112 | '𑊩', // U+112A9 BC=L BLK=Multani SC=Multani MULTANI SECTION MARK 113 | '𑑋', // U+1144B BC=L BLK=Newa SC=Newa NEWA DANDA 114 | '𑑌', // U+1144C BC=L BLK=Newa SC=Newa NEWA DOUBLE DANDA 115 | '𑗂', // U+115C2 BC=L BLK=Siddham SC=Siddham SIDDHAM DANDA 116 | '𑗃', // U+115C3 BC=L BLK=Siddham SC=Siddham SIDDHAM DOUBLE DANDA 117 | '𑗉', // U+115C9 BC=L BLK=Siddham SC=Siddham SIDDHAM END OF TEXT MARK 118 | '𑗊', // U+115CA BC=L BLK=Siddham SC=Siddham SIDDHAM SECTION MARK WITH TRIDENT AND U-SHAPED ORNAMENTS 119 | '𑗋', // U+115CB BC=L BLK=Siddham SC=Siddham SIDDHAM SECTION MARK WITH TRIDENT AND DOTTED CRESCENTS 120 | '𑗌', // U+115CC BC=L BLK=Siddham SC=Siddham SIDDHAM SECTION MARK WITH RAYS AND DOTTED CRESCENTS 121 | '𑗍', // U+115CD BC=L BLK=Siddham SC=Siddham SIDDHAM SECTION MARK WITH RAYS AND DOTTED DOUBLE CRESCENTS 122 | '𑗎', // U+115CE BC=L BLK=Siddham SC=Siddham SIDDHAM SECTION MARK WITH RAYS AND DOTTED TRIPLE CRESCENTS 123 | '𑗏', // U+115CF BC=L BLK=Siddham SC=Siddham SIDDHAM SECTION MARK DOUBLE RING 124 | '𑗐', // U+115D0 BC=L BLK=Siddham SC=Siddham SIDDHAM SECTION MARK DOUBLE RING WITH RAYS 125 | '𑗑', // U+115D1 BC=L BLK=Siddham SC=Siddham SIDDHAM SECTION MARK WITH DOUBLE CRESCENTS 126 | '𑗒', // U+115D2 BC=L BLK=Siddham SC=Siddham SIDDHAM SECTION MARK WITH TRIPLE CRESCENTS 127 | '𑗓', // U+115D3 BC=L BLK=Siddham SC=Siddham SIDDHAM SECTION MARK WITH QUADRUPLE CRESCENTS 128 | '𑗔', // U+115D4 BC=L BLK=Siddham SC=Siddham SIDDHAM SECTION MARK WITH SEPTUPLE CRESCENTS 129 | '𑗕', // U+115D5 BC=L BLK=Siddham SC=Siddham SIDDHAM SECTION MARK WITH CIRCLES AND RAYS 130 | '𑗖', // U+115D6 BC=L BLK=Siddham SC=Siddham SIDDHAM SECTION MARK WITH CIRCLES AND TWO ENCLOSURES 131 | '𑗗', // U+115D7 BC=L BLK=Siddham SC=Siddham SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES 132 | '𑙁', // U+11641 BC=L BLK=Modi SC=Modi MODI DANDA 133 | '𑙂', // U+11642 BC=L BLK=Modi SC=Modi MODI DOUBLE DANDA 134 | '𑜼', // U+1173C BC=L BLK=Ahom SC=Ahom AHOM SIGN SMALL SECTION 135 | '𑜽', // U+1173D BC=L BLK=Ahom SC=Ahom AHOM SIGN SECTION 136 | '𑜾', // U+1173E BC=L BLK=Ahom SC=Ahom AHOM SIGN RULAI 137 | '𑥄', // U+11944 BC=L BLK=Dives_Akuru SC=Dives_Akuru DIVES AKURU DOUBLE DANDA 138 | '𑥆', // U+11946 BC=L BLK=Dives_Akuru SC=Dives_Akuru DIVES AKURU END OF TEXT MARK 139 | '𑩂', // U+11A42 BC=L BLK=Zanabazar_Square SC=Zanabazar_Square ZANABAZAR SQUARE MARK SHAD 140 | '𑩃', // U+11A43 BC=L BLK=Zanabazar_Square SC=Zanabazar_Square ZANABAZAR SQUARE MARK DOUBLE SHAD 141 | '𑪛', // U+11A9B BC=L BLK=Soyombo SC=Soyombo SOYOMBO MARK SHAD 142 | '𑪜', // U+11A9C BC=L BLK=Soyombo SC=Soyombo SOYOMBO MARK DOUBLE SHAD 143 | '𑱁', // U+11C41 BC=L BLK=Bhaiksuki SC=Bhaiksuki BHAIKSUKI DANDA 144 | '𑱂', // U+11C42 BC=L BLK=Bhaiksuki SC=Bhaiksuki BHAIKSUKI DOUBLE DANDA 145 | '𑻷', // U+11EF7 BC=L BLK=Makasar SC=Makasar MAKASAR PASSIMBANG 146 | '𑻸', // U+11EF8 BC=L BLK=Makasar SC=Makasar MAKASAR END OF SECTION 147 | '𑽃', // U+11F43 BC=L BLK=Kawi SC=Kawi KAWI DANDA 148 | '𑽄', // U+11F44 BC=L BLK=Kawi SC=Kawi KAWI DOUBLE DANDA 149 | '𖩮', // U+16A6E BC=L BLK=Mro SC=Mro MRO DANDA 150 | '𖩯', // U+16A6F BC=L BLK=Mro SC=Mro MRO DOUBLE DANDA 151 | '𖫵', // U+16AF5 BC=L BLK=Bassa_Vah SC=Bassa_Vah BASSA VAH FULL STOP 152 | '𖬷', // U+16B37 BC=L BLK=Pahawh_Hmong SC=Pahawh_Hmong PAHAWH HMONG SIGN VOS THOM 153 | '𖬸', // U+16B38 BC=L BLK=Pahawh_Hmong SC=Pahawh_Hmong PAHAWH HMONG SIGN VOS TSHAB CEEB 154 | '𖭄', // U+16B44 BC=L BLK=Pahawh_Hmong SC=Pahawh_Hmong PAHAWH HMONG SIGN XAUS 155 | '𖺘', // U+16E98 BC=L BLK=Medefaidrin SC=Medefaidrin MEDEFAIDRIN FULL STOP 156 | '𛲟', // U+1BC9F BC=L BLK=Duployan SC=Duployan DUPLOYAN PUNCTUATION CHINOOK FULL STOP 157 | '𝪈' // U+1DA88 BC=L BLK=Sutton_SignWriting SC=SignWriting SIGNWRITING FULL STOP 158 | ].concat([ 159 | // Additional manual entries. 160 | '。', // U+3002 IDEOGRAPHIC FULL STOP 161 | '。' // U+FF61 HALFWIDTH IDEOGRAPHIC FULL STOP 162 | ]) 163 | 164 | export default GLOBAL_SENTENCE_TERMINATORS 165 | -------------------------------------------------------------------------------- /test/de.test.js: -------------------------------------------------------------------------------- 1 | import segment from '../src/index.js' 2 | import assert from 'assert' 3 | 4 | const tests = { 5 | 6 | '„Ich habe heute keine Zeit“, sagte die Frau und flüsterte leise: „Und auch keine Lust.“ Wir haben 1.000.000 Euro.': 7 | [ 8 | '„Ich habe heute keine Zeit“, sagte die Frau und flüsterte leise: „Und auch keine Lust.“', 9 | 'Wir haben 1.000.000 Euro.' 10 | ], 11 | 12 | 'Es gibt jedoch einige Vorsichtsmaßnahmen, die Du ergreifen kannst, z. B. ist es sehr empfehlenswert, dass Du Dein Zuhause von allem Junkfood befreist.': 13 | [ 14 | 'Es gibt jedoch einige Vorsichtsmaßnahmen, die Du ergreifen kannst, z. B. ist es sehr empfehlenswert, dass Du Dein Zuhause von allem Junkfood befreist.' 15 | ], 16 | 17 | 'Was sind die Konsequenzen der Abstimmung vom 12. Juni?': 18 | ['Was sind die Konsequenzen der Abstimmung vom 12. Juni?'], 19 | 20 | // pytest.param( 21 | // "Thomas sagte: ,,Wann kommst zu mir?” ,,Das weiß ich noch nicht“, antwortete Susi, ,,wahrscheinlich am Sonntag.“ Wir haben 1.000.000 Euro.", 22 | // [ 23 | // "Thomas sagte: ,,Wann kommst zu mir?” ,,Das weiß ich noch nicht“, antwortete Susi, ,,wahrscheinlich am Sonntag.“", 24 | // "Wir haben 1.000.000 Euro.", 25 | // ], 26 | // marks=pytest.mark.xfail, 27 | 28 | // "„Lass uns jetzt essen gehen!“, sagte die Mutter zu ihrer Freundin, „am besten zum Italiener.“", 29 | // [ 30 | // "„Lass uns jetzt essen gehen!“, sagte die Mutter zu ihrer Freundin, „am besten zum Italiener.“" 31 | // ], 32 | 33 | 'Wir haben 1.000.000 Euro.': ['Wir haben 1.000.000 Euro.'], 34 | 'Sie bekommen 3,50 Euro zurück.': ['Sie bekommen 3,50 Euro zurück.'], 35 | 'Dafür brauchen wir 5,5 Stunden.': ['Dafür brauchen wir 5,5 Stunden.'], 36 | 'Bitte überweisen Sie 5.300,25 Euro.': ['Bitte überweisen Sie 5.300,25 Euro.'], 37 | // pytest.param( 38 | // "1. Dies ist eine Punkteliste.", 39 | // ["1. Dies ist eine Punkteliste."], 40 | // marks=pytest.mark.xfail, 41 | 42 | 'Wir trafen Dr. med. Meyer in der Stadt.': ['Wir trafen Dr. med. Meyer in der Stadt.'], 43 | 44 | 'Wir brauchen Getränke, z. B. Wasser, Saft, Bier usw.': ['Wir brauchen Getränke, z. B. Wasser, Saft, Bier usw.'], 45 | 46 | 'Ich kann u.a. Spanisch sprechen.': ['Ich kann u.a. Spanisch sprechen.'], 47 | 'Frau Prof. Schulze ist z. Z. nicht da.': ['Frau Prof. Schulze ist z. Z. nicht da.'], 48 | 'Sie erhalten ein neues Bank-Statement bzw. ein neues Schreiben.': ['Sie erhalten ein neues Bank-Statement bzw. ein neues Schreiben.'], 49 | 50 | 'Z. T. ist die Lieferung unvollständig.': ['Z. T. ist die Lieferung unvollständig.'], 51 | 'Das finden Sie auf S. 225.': ['Das finden Sie auf S. 225.'], 52 | 'Sie besucht eine kath. Schule.': ['Sie besucht eine kath. Schule.'], 53 | 'Wir benötigen Zeitungen, Zeitschriften u. Ä. für unser Projekt.': ['Wir benötigen Zeitungen, Zeitschriften u. Ä. für unser Projekt.'], 54 | 55 | 'Das steht auf S. 23, s. vorherige Anmerkung.': ['Das steht auf S. 23, s. vorherige Anmerkung.'], 56 | 57 | 'Dies ist meine Adresse: Dr. Meier, Berliner Str. 5, 21234 Bremen.': ['Dies ist meine Adresse: Dr. Meier, Berliner Str. 5, 21234 Bremen.'], 58 | 59 | 'Er sagte: „Hallo, wie geht´s Ihnen, Frau Prof. Müller?“': ['Er sagte: „Hallo, wie geht´s Ihnen, Frau Prof. Müller?“'], 60 | 61 | // pytest.param( 62 | // "Fit in vier Wochen\n\nDeine Anleitung für eine reine Ernährung und ein gesünderes und glücklicheres Leben\n\nRECHTLICHE HINWEISE\n\nOhne die ausdrückliche schriftliche Genehmigung der Eigentümerin von instafemmefitness, Anna Anderson, darf dieses E-Book weder teilweise noch in vollem Umfang reproduziert, gespeichert, kopiert oder auf irgendeine Weise übertragen werden. Wenn Du das E-Book auf einem öffentlich zugänglichen Computer ausdruckst, musst Du es nach dem Ausdrucken von dem Computer löschen. Jedes E-Book wird mit einem Benutzernamen und Transaktionsinformationen versehen.\n\nVerstöße gegen dieses Urheberrecht werden im vollen gesetzlichen Umfang geltend gemacht. Obgleich die Autorin und Herausgeberin alle Anstrengungen unternommen hat, sicherzustellen, dass die Informationen in diesem Buch zum Zeitpunkt der Drucklegung korrekt sind, übernimmt die Autorin und Herausgeberin keine Haftung für etwaige Verluste, Schäden oder Störungen, die durch Fehler oder Auslassungen in Folge von Fahrlässigkeit, zufälligen Umständen oder sonstigen Ursachen entstehen, und lehnt hiermit jedwede solche Haftung ab.\n\nDieses Buch ist kein Ersatz für die medizinische Beratung durch Ärzte. Der Leser/die Leserin sollte regelmäßig einen Arzt/eine Ärztin hinsichtlich Fragen zu seiner/ihrer Gesundheit und vor allem in Bezug auf Symptome, die eventuell einer ärztlichen Diagnose oder Behandlung bedürfen, konsultieren.\n\nDie Informationen in diesem Buch sind dazu gedacht, ein ordnungsgemäßes Training zu ergänzen, nicht aber zu ersetzen. Wie jeder andere Sport, der Geschwindigkeit, Ausrüstung, Gleichgewicht und Umweltfaktoren einbezieht, stellt dieser Sport ein gewisses Risiko dar. Die Autorin und Herausgeberin rät den Lesern dazu, die volle Verantwortung für die eigene Sicherheit zu übernehmen und die eigenen Grenzen zu beachten. Vor dem Ausüben der in diesem Buch beschriebenen Übungen solltest Du sicherstellen, dass Deine Ausrüstung in gutem Zustand ist, und Du solltest keine Risiken außerhalb Deines Erfahrungs- oder Trainingsniveaus, Deiner Fähigkeiten oder Deines Komfortbereichs eingehen.\nHintergrundillustrationen Urheberrecht © 2013 bei Shuttershock, Buchgestaltung und -produktion durch Anna Anderson Verfasst von Anna Anderson\nUrheberrecht © 2014 Instafemmefitness. Alle Rechte vorbehalten\n\nÜber mich", 63 | // [ 64 | // "Fit in vier Wochen", 65 | // "Deine Anleitung für eine reine Ernährung und ein gesünderes und glücklicheres Leben", 66 | // "RECHTLICHE HINWEISE", 67 | // "Ohne die ausdrückliche schriftliche Genehmigung der Eigentümerin von instafemmefitness, Anna Anderson, darf dieses E-Book weder teilweise noch in vollem Umfang reproduziert, gespeichert, kopiert oder auf irgendeine Weise übertragen werden.", 68 | // "Wenn Du das E-Book auf einem öffentlich zugänglichen Computer ausdruckst, musst Du es nach dem Ausdrucken von dem Computer löschen.", 69 | // "Jedes E-Book wird mit einem Benutzernamen und Transaktionsinformationen versehen.", 70 | // "Verstöße gegen dieses Urheberrecht werden im vollen gesetzlichen Umfang geltend gemacht.", 71 | // "Obgleich die Autorin und Herausgeberin alle Anstrengungen unternommen hat, sicherzustellen, dass die Informationen in diesem Buch zum Zeitpunkt der Drucklegung korrekt sind, übernimmt die Autorin und Herausgeberin keine Haftung für etwaige Verluste, Schäden oder Störungen, die durch Fehler oder Auslassungen in Folge von Fahrlässigkeit, zufälligen Umständen oder sonstigen Ursachen entstehen, und lehnt hiermit jedwede solche Haftung ab.", 72 | // "Dieses Buch ist kein Ersatz für die medizinische Beratung durch Ärzte.", 73 | // "Der Leser/die Leserin sollte regelmäßig einen Arzt/eine Ärztin hinsichtlich Fragen zu seiner/ihrer Gesundheit und vor allem in Bezug auf Symptome, die eventuell einer ärztlichen Diagnose oder Behandlung bedürfen, konsultieren.", 74 | // "Die Informationen in diesem Buch sind dazu gedacht, ein ordnungsgemäßes Training zu ergänzen, nicht aber zu ersetzen.", 75 | // "Wie jeder andere Sport, der Geschwindigkeit, Ausrüstung, Gleichgewicht und Umweltfaktoren einbezieht, stellt dieser Sport ein gewisses Risiko dar.", 76 | // "Die Autorin und Herausgeberin rät den Lesern dazu, die volle Verantwortung für die eigene Sicherheit zu übernehmen und die eigenen Grenzen zu beachten.", 77 | // "Vor dem Ausüben der in diesem Buch beschriebenen Übungen solltest Du sicherstellen, dass Deine Ausrüstung in gutem Zustand ist, und Du solltest keine Risiken außerhalb Deines Erfahrungs- oder Trainingsniveaus, Deiner Fähigkeiten oder Deines Komfortbereichs eingehen.", 78 | // "Hintergrundillustrationen Urheberrecht © 2013 bei Shuttershock, Buchgestaltung und -produktion durch Anna Anderson Verfasst von Anna Anderson", 79 | // "Urheberrecht © 2014 Instafemmefitness.", 80 | // "Alle Rechte vorbehalten", 81 | // "Über mich", 82 | // ], 83 | // marks=pytest.mark.xfail, 84 | // 85 | // pytest.param( 86 | // "Es gibt jedoch einige Vorsichtsmaßnahmen, die Du ergreifen kannst, z. B. ist es sehr empfehlenswert, dass Du Dein Zuhause von allem Junkfood befreist. Ich persönlich kaufe kein Junkfood oder etwas, das nicht rein ist (ich traue mir da selbst nicht!). Ich finde jeden Vorwand, um das Junkfood zu essen, vor allem die Vorstellung, dass ich nicht mehr in Versuchung kommen werde, wenn ich es jetzt aufesse und es weg ist. Es ist schon komisch, was unser Verstand mitunter anstellt!", 87 | // [ 88 | // "Es gibt jedoch einige Vorsichtsmaßnahmen, die Du ergreifen kannst, z. B. ist es sehr empfehlenswert, dass Du Dein Zuhause von allem Junkfood befreist.", 89 | // "Ich persönlich kaufe kein Junkfood oder etwas, das nicht rein ist (ich traue mir da selbst nicht!).", 90 | // "Ich finde jeden Vorwand, um das Junkfood zu essen, vor allem die Vorstellung, dass ich nicht mehr in Versuchung kommen werde, wenn ich es jetzt aufesse und es weg ist.", 91 | // "Es ist schon komisch, was unser Verstand mitunter anstellt!", 92 | // ], 93 | // marks=pytest.mark.xfail, 94 | // 95 | // pytest.param( 96 | // "Ob Sie in Hannover nur auf der Durchreise, für einen längeren Aufenthalt oder zum Besuch einer der zahlreichen Messen sind: Die Hauptstadt des Landes Niedersachsens hat viele Sehenswürdigkeiten und ist zu jeder Jahreszeit eine Reise Wert. Hannovers Ursprünge können bis zur römischen Kaiserzeit zurückverfolgt werden, und zwar durch Ausgrabungen von Tongefäßen aus dem 1. -3. Jahrhundert nach Christus, die an mehreren Stellen im Untergrund des Stadtzentrums durchgeführt wurden.", 97 | // [ 98 | // "Ob Sie in Hannover nur auf der Durchreise, für einen längeren Aufenthalt oder zum Besuch einer der zahlreichen Messen sind: Die Hauptstadt des Landes Niedersachsens hat viele Sehenswürdigkeiten und ist zu jeder Jahreszeit eine Reise Wert.", 99 | // "Hannovers Ursprünge können bis zur römischen Kaiserzeit zurückverfolgt werden, und zwar durch Ausgrabungen von Tongefäßen aus dem 1. -3. Jahrhundert nach Christus, die an mehreren Stellen im Untergrund des Stadtzentrums durchgeführt wurden.", 100 | // ], 101 | // marks=pytest.mark.xfail, 102 | // 103 | // pytest.param( 104 | // "• 3. Seien Sie achtsam bei der Auswahl der Nahrungsmittel! \n• 4. Nehmen Sie zusätzlich Folsäurepräparate und essen Sie Fisch! \n• 5. Treiben Sie regelmäßig Sport! \n• 6. Beginnen Sie mit Übungen für die Beckenbodenmuskulatur! \n• 7. Reduzieren Sie Ihren Alkoholgenuss! \n", 105 | // [ 106 | // "• 3. Seien Sie achtsam bei der Auswahl der Nahrungsmittel!", 107 | // "• 4. Nehmen Sie zusätzlich Folsäurepräparate und essen Sie Fisch!", 108 | // "• 5. Treiben Sie regelmäßig Sport!", 109 | // "• 6. Beginnen Sie mit Übungen für die Beckenbodenmuskulatur!", 110 | // "• 7. Reduzieren Sie Ihren Alkoholgenuss!", 111 | // ], 112 | // marks=pytest.mark.xfail, 113 | // 114 | 115 | 'Was pro Jahr10. Zudem pro Jahr um 0.3 %11. Der gängigen Theorie nach erfolgt der Anstieg.': [ 116 | 'Was pro Jahr10.', 117 | 'Zudem pro Jahr um 0.3 %11.', 118 | 'Der gängigen Theorie nach erfolgt der Anstieg.' 119 | ], 120 | 121 | 's. vorherige Anmerkung.': ['s. vorherige Anmerkung.'], 122 | 123 | 'Mit Inkrafttreten des Mindestlohngesetzes (MiLoG) zum 01. Januar 2015 werden in Bezug auf den Einsatz von Leistungs.': [ 124 | 'Mit Inkrafttreten des Mindestlohngesetzes (MiLoG) zum 01. Januar 2015 werden in Bezug auf den Einsatz von Leistungs.' 125 | ] 126 | 127 | // pytest.param( 128 | // "\n• einige Sorten Weichkäse \n• rohes oder nicht ganz durchgebratenes Fleisch \n• ungeputztes Gemüse und ungewaschener Salat \n• nicht ganz durchgebratenes Hühnerfleisch, rohe oder nur weich gekochte Eier", 129 | // [ 130 | // "\n", 131 | // "• einige Sorten Weichkäse", 132 | // "• rohes oder nicht ganz durchgebratenes Fleisch", 133 | // "• ungeputztes Gemüse und ungewaschener Salat", 134 | // "• nicht ganz durchgebratenes Hühnerfleisch, rohe oder nur weich gekochte Eier", 135 | // ], 136 | // marks=pytest.mark.xfail, 137 | // 138 | 139 | } 140 | 141 | describe('Deutsch segment()', function () { 142 | for (const [text, expectedSentences] of Object.entries(tests)) { 143 | it(`correctly segments text: ${text}`, function () { 144 | const sentences = segment('de', text) 145 | assert.deepEqual(sentences, expectedSentences) 146 | }) 147 | } 148 | }) 149 | -------------------------------------------------------------------------------- /src/languages/nl.js: -------------------------------------------------------------------------------- 1 | import BaseLanguage from '../base.js' 2 | 3 | const abbreviations = new Set([ 4 | 'riv.dir.int."le priv', 5 | '2d', 6 | '3e', 7 | 'a.2d', 8 | 'a.a.j.b', 9 | 'a.a', 10 | 'a.f.t', 11 | 'a.g.j.b', 12 | 'a.h.v', 13 | 'a.h.w', 14 | 'a.hosp', 15 | 'a.i', 16 | 'a.j.b', 17 | 'a.j.t', 18 | 'a.m.r', 19 | 'a.m', 20 | 'a.p.m', 21 | 'a.p.r', 22 | 'a.p.t', 23 | 'a.s', 24 | 'a.t.d.f', 25 | 'a.u.b', 26 | 'a.v.a', 27 | 'a.w', 28 | 'aanbev.comm', 29 | 'aanbev', 30 | 'aant', 31 | 'aanv.st', 32 | 'aanw.vnw', 33 | 'aanw', 34 | 'abd', 35 | 'abm', 36 | 'abs', 37 | 'acc.& fisc', 38 | 'acc.act', 39 | 'acc.bedr.m', 40 | 'acc.bedr.t', 41 | "acc.thema's m.", 42 | 'acc.thema’s m', 43 | 'achterv', 44 | 'act.dr.fam', 45 | 'act.dr', 46 | 'act.fisc', 47 | 'act.soc', 48 | 'adm.akk', 49 | 'adm.besl', 50 | 'adm.lex', 51 | 'adm.onderr', 52 | 'adm.ov', 53 | 'adv.bl', 54 | 'adv', 55 | 'afd', 56 | 'afl', 57 | 'aggl.verord', 58 | 'agr', 59 | 'al', 60 | 'alg.richts', 61 | 'alg', 62 | 'amén', 63 | 'ann.dr.lg', 64 | 'ann.dr.sc.pol', 65 | 'ann.dr', 66 | 'ann.ét.eur', 67 | 'ann.fac.dr.lg', 68 | 'ann.jur.créd.règl.coll', 69 | 'ann.jur.créd', 70 | 'ann.not', 71 | 'ann.parl', 72 | 'ann.prat.comm', 73 | 'app', 74 | 'arb', 75 | 'arbbl', 76 | 'arbh', 77 | 'arbit.besl', 78 | 'arbrb', 79 | 'arr.cass', 80 | 'arr.r.v.st', 81 | 'arr.verbr', 82 | 'arr', 83 | 'arrondrb', 84 | 'art', 85 | 'artw', 86 | 'aud', 87 | 'b.&w', 88 | 'b.a.s', 89 | 'b.a', 90 | 'b.b.o', 91 | 'b.best.dep', 92 | 'b.br.ex', 93 | 'b.coll.fr.gem.comm', 94 | 'b.coll.vl.gem.comm', 95 | 'b.d.cult.r', 96 | 'b.d.gem.ex', 97 | 'b.d.gem.reg', 98 | 'b.dep', 99 | 'b.e.b', 100 | 'b.f.r', 101 | 'b.fr.gem.ex', 102 | 'b.fr.gem.reg', 103 | 'b.i.h', 104 | 'b.inl.j.d', 105 | 'b.inl.s.reg', 106 | 'b.j', 107 | 'b.l', 108 | 'b.lid br.ex', 109 | 'b.lid d.gem.ex', 110 | 'b.lid fr.gem.ex', 111 | 'b.lid vl.ex', 112 | 'b.lid w.gew.ex', 113 | 'b.o.z', 114 | 'b.prov.r', 115 | 'b.r.h', 116 | 'b.s', 117 | 'b.sr', 118 | 'b.stb', 119 | 'b.t.i.r', 120 | 'b.t.s.z', 121 | 'b.t.w.rev', 122 | 'b.v', 123 | 'b.ver.coll.gem.gem.comm', 124 | 'b.verg.r.b', 125 | 'b.versl', 126 | 'b.vl.ex', 127 | 'b.voorl.reg', 128 | 'b.w.gew.ex', 129 | 'b.w', 130 | 'b.z.d.g', 131 | 'b.z.v', 132 | 'b', 133 | 'bab', 134 | 'bank fin.r', 135 | 'bank fin', 136 | 'bedr.org', 137 | 'begins', 138 | 'beheersov', 139 | 'bekendm.comm', 140 | 'bel.besch', 141 | 'bel.w.p', 142 | 'bel', 143 | 'beleidsov', 144 | 'belg', 145 | 'benelux jur', 146 | 'ber.w', 147 | 'ber', 148 | 'besch', 149 | 'besl', 150 | 'beslagr', 151 | 'besluitwet nr', 152 | 'best', 153 | 'bestuurswet', 154 | 'bet', 155 | 'betr', 156 | 'bevest', 157 | 'bew', 158 | 'bijbl.n.bijdr', 159 | 'bijbl', 160 | 'bijl', 161 | 'bijv', 162 | 'bijw', 163 | 'bijz.decr', 164 | 'bin.b', 165 | 'bkh', 166 | 'bl', 167 | 'blz', 168 | 'bm', 169 | 'bn', 170 | 'bnlx merkw', 171 | 'bnlx tek', 172 | 'bnlx uitl', 173 | 'bnw', 174 | 'bouwr', 175 | 'br drs', 176 | 'br.parl', 177 | 'bs', 178 | 'bt drs', 179 | 'btw rev', 180 | 'bull.adm.pénit', 181 | 'bull.ass', 182 | 'bull.b.m.m', 183 | 'bull.bel', 184 | 'bull.best.strafinr', 185 | 'bull.bmm', 186 | 'bull.c.b.n', 187 | 'bull.c.n.c', 188 | 'bull.cbn', 189 | 'bull.centr.arb', 190 | 'bull.cnc', 191 | 'bull.contr', 192 | 'bull.doc.min.fin', 193 | 'bull.f.e.b', 194 | 'bull.feb', 195 | 'bull.fisc.fin.r', 196 | 'bull.i.u.m', 197 | 'bull.inf.ass.secr.soc', 198 | 'bull.inf.i.e.c', 199 | 'bull.inf.i.n.a.m.i', 200 | 'bull.inf.i.r.e', 201 | 'bull.inf.iec', 202 | 'bull.inf.inami', 203 | 'bull.inf.ire', 204 | 'bull.inst.arb', 205 | 'bull.ium', 206 | 'bull.jur.imm', 207 | 'bull.lég.b', 208 | 'bull.off', 209 | 'bull.trim.b.dr.comp', 210 | 'bull.us', 211 | 'bull.v.b.o', 212 | 'bull.vbo', 213 | 'bull', 214 | 'bv i.o', 215 | 'bv', 216 | 'bw int.reg', 217 | 'bw', 218 | 'bxh', 219 | 'byz', 220 | 'c.& f.p', 221 | 'c.& f', 222 | 'c.a.-a', 223 | 'c.a.b.g', 224 | 'c.a', 225 | 'c.c.i', 226 | 'c.c.s', 227 | 'c.c', 228 | 'c.conc.jur', 229 | 'c.d.e', 230 | 'c.d.p.k', 231 | 'c.e', 232 | 'c.ex', 233 | 'c.f', 234 | 'c.h.a', 235 | 'c.i.f.i.c', 236 | 'c.i.f', 237 | 'c.j', 238 | 'c.l', 239 | 'c.n', 240 | 'c.o.d', 241 | 'c.p', 242 | 'c.pr.civ', 243 | 'c.q', 244 | 'c.r.a', 245 | 'c.r', 246 | 'c.s.a', 247 | 'c.s.q.n', 248 | 'c.s', 249 | 'c.v.a', 250 | 'c.v.o', 251 | 'c.v', 252 | 'c', 253 | 'ca', 254 | 'cadeaust', 255 | 'cah.const', 256 | 'cah.dr.europ', 257 | 'cah.dr.immo', 258 | 'cah.dr.jud', 259 | 'cal', 260 | 'cap', 261 | 'carg', 262 | 'cas', 263 | 'cass', 264 | 'cert', 265 | 'cf', 266 | 'ch', 267 | 'chr', 268 | 'chron.d.s', 269 | 'chron.dr.not', 270 | 'chron', 271 | 'cie', 272 | 'cir', 273 | 'circ.z', 274 | 'circ', 275 | 'cit.loc', 276 | 'cit', 277 | 'civ', 278 | 'cl.et.b', 279 | 'cmt', 280 | 'co', 281 | 'cognoss.v', 282 | 'coll', 283 | 'colp.w', 284 | 'com.v.min', 285 | 'com', 286 | 'comm.bijz.ov', 287 | 'comm.erf', 288 | 'comm.fin', 289 | 'comm.ger', 290 | 'comm.handel', 291 | 'comm.pers', 292 | 'comm.pub', 293 | 'comm.straf', 294 | 'comm.v.en v', 295 | 'comm.v', 296 | 'comm.venn', 297 | 'comm.verz', 298 | 'comm.voor', 299 | 'comm', 300 | 'comp', 301 | 'compt.w', 302 | 'computerr', 303 | 'con.m', 304 | 'concl', 305 | 'concr', 306 | 'conf', 307 | 'confl.w.huwbetr', 308 | 'confl.w', 309 | 'cons', 310 | 'conv', 311 | 'coöp', 312 | 'corr.bl', 313 | 'corr', 314 | 'cour de cass', 315 | 'cour.fisc', 316 | 'cour.immo', 317 | 'cridon', 318 | 'crim', 319 | 'crt', 320 | 'cur', 321 | 'curs', 322 | 'd.-g', 323 | 'd.a.v', 324 | 'd.a', 325 | 'd.b.f', 326 | 'd.c.c.r', 327 | 'd.c', 328 | 'd.d.p', 329 | 'd.d', 330 | 'd.e.t', 331 | 'd.gem.r', 332 | 'd.h.z', 333 | 'd.h', 334 | 'd.i.t', 335 | 'd.i', 336 | 'd.j', 337 | 'd.l.r', 338 | 'd.m.v', 339 | 'd.m', 340 | 'd.o.v', 341 | 'd.parl', 342 | 'd.w.z', 343 | 'd', 344 | 'dact', 345 | 'dat', 346 | 'dbesch', 347 | 'dbesl', 348 | 'de advoc', 349 | 'de belg.acc', 350 | 'de burg.st', 351 | 'de dr', 352 | 'de gem', 353 | 'de gerechtsd', 354 | 'de venn', 355 | 'de verz', 356 | 'decr.d', 357 | 'decr.fr', 358 | 'decr.vl', 359 | 'decr.w', 360 | 'decr', 361 | 'deelw', 362 | 'def', 363 | 'dep.opv', 364 | 'dep.rtl', 365 | 'derg', 366 | 'desp', 367 | 'det.mag', 368 | 'deurw.regl', 369 | 'dez', 370 | 'dgl', 371 | 'dhr', 372 | 'disp', 373 | 'diss', 374 | 'div.act', 375 | 'div.bel', 376 | 'div', 377 | 'dl', 378 | 'dln', 379 | 'dnotz', 380 | 'doc.jur.b', 381 | 'doc.min.fin', 382 | 'doc.parl', 383 | 'doc', 384 | 'doctr', 385 | 'dpl.besl', 386 | 'dpl', 387 | 'dr.banc.fin', 388 | 'dr.circ', 389 | 'dr.inform', 390 | 'dr.mr', 391 | 'dr.pén.entr', 392 | 'dr.q.m', 393 | 'dr', 394 | 'drs', 395 | 'dtp', 396 | 'dwz', 397 | 'dyn', 398 | 'e cont', 399 | 'e.a', 400 | 'e.b', 401 | 'e.c.a', 402 | 'e.c', 403 | 'e.d', 404 | 'e.e.a', 405 | 'e.e.g', 406 | 'e.e', 407 | 'e.g.a', 408 | 'e.g', 409 | 'e.h.a', 410 | 'e.i', 411 | 'e.j', 412 | 'e.m.a', 413 | 'e.n.a.c', 414 | 'e.o', 415 | 'e.p.c', 416 | 'e.r.c', 417 | 'e.r.f', 418 | 'e.r.h', 419 | 'e.r.o', 420 | 'e.r.p', 421 | 'e.r.v', 422 | 'e.s.r.a', 423 | 'e.s.t', 424 | 'e.v.a', 425 | 'e.v', 426 | 'e.w', 427 | 'e', 428 | 'e&o.e', 429 | 'ec.pol.r', 430 | 'echos log', 431 | 'econ', 432 | 'ed', 433 | 'ed(s)', 434 | 'eeg verd.v', 435 | 'eex san s', 436 | 'eff', 437 | 'eg rtl', 438 | 'eig.mag', 439 | 'eig', 440 | 'eil', 441 | 'elektr', 442 | 'en antw', 443 | 'en gew', 444 | 'en m', 445 | 'en prov', 446 | 'en s', 447 | 'en w', 448 | 'enmb', 449 | 'entr.et dr', 450 | 'enz', 451 | 'err', 452 | 'et al', 453 | 'et seq', 454 | 'etc', 455 | 'etq', 456 | 'eur.t.s', 457 | 'eur.verd.overdracht strafv', 458 | 'eur', 459 | 'ev rechtsh', 460 | 'ev uitl', 461 | 'ev', 462 | 'evt', 463 | 'ex.crim', 464 | 'ex', 465 | 'exec', 466 | 'f.a.o', 467 | 'f.a.q', 468 | 'f.a.s', 469 | 'f.i.b', 470 | 'f.j.f', 471 | 'f.o.b', 472 | 'f.o.r', 473 | 'f.o.s', 474 | 'f.o.t', 475 | 'f.r', 476 | 'f.supp', 477 | 'f.suppl', 478 | 'f', 479 | 'fa', 480 | 'facs', 481 | 'fare act', 482 | 'fasc', 483 | 'fg', 484 | 'fid.ber', 485 | 'fig', 486 | 'fin.verh.w', 487 | 'fin', 488 | 'fisc.act', 489 | 'fisc.koer', 490 | 'fisc', 491 | 'fl', 492 | 'form', 493 | 'foro', 494 | 'fr.cult.r', 495 | 'fr.gem.r', 496 | 'fr.parl', 497 | 'fr', 498 | 'fra', 499 | 'ft', 500 | 'g.a.v', 501 | 'g.a.w.v', 502 | 'g.a', 503 | 'g.g.d', 504 | 'g.m.t', 505 | 'g.o', 506 | 'g.omt.e', 507 | 'g.p', 508 | 'g.s', 509 | 'g.v', 510 | 'g.w.w', 511 | 'g', 512 | 'geb', 513 | 'gebr', 514 | 'gebrs', 515 | 'gec.decr', 516 | 'gec', 517 | 'ged.st', 518 | 'ged', 519 | 'gedipl', 520 | 'gedr.st', 521 | 'geh', 522 | 'gem.comm', 523 | 'gem.gem.comm', 524 | 'gem.st', 525 | 'gem.stem', 526 | 'gem.w', 527 | 'gem.wet, gem.wet', 528 | 'gem', 529 | 'gemeensch.optr', 530 | 'gemeensch.standp', 531 | 'gemeensch.strat', 532 | 'gemeent.b', 533 | 'gemeent.regl', 534 | 'gemeent.verord', 535 | 'gemeent', 536 | 'gen', 537 | 'geol', 538 | 'geopp', 539 | 'gepubl', 540 | 'ger.deurw', 541 | 'ger.w', 542 | 'gerekw', 543 | 'gereq', 544 | 'gesch', 545 | 'get', 546 | 'getr', 547 | 'gev.m', 548 | 'gev.maatr', 549 | 'gew', 550 | 'ghert', 551 | 'gir.eff.verk', 552 | 'gk', 553 | 'gr', 554 | 'gramm', 555 | 'grat.w', 556 | 'gron,opm.en leermed', 557 | 'grondw', 558 | 'grootb.w', 559 | 'grs', 560 | 'grur ausl', 561 | 'grur int', 562 | 'grvm', 563 | 'grw', 564 | 'gst', 565 | 'gw', 566 | 'h.a.v.o', 567 | 'h.a', 568 | 'h.b.o', 569 | 'h.e.a.o', 570 | 'h.e.g.a', 571 | 'h.e.geb', 572 | 'h.e.gestr', 573 | 'h.l', 574 | 'h.m', 575 | 'h.o', 576 | 'h.r', 577 | 'h.t.l', 578 | 'h.t.m', 579 | 'h.w.geb', 580 | 'hand', 581 | 'handelsn.w', 582 | 'handelspr', 583 | 'handelsr.w', 584 | 'handelsreg.w', 585 | 'handv', 586 | 'harv.l.rev', 587 | 'hc', 588 | 'herald', 589 | 'hert', 590 | 'herz', 591 | 'hfdst', 592 | 'hfst', 593 | 'hgrw', 594 | 'hhr', 595 | 'hist', 596 | 'hooggel', 597 | 'hoogl', 598 | 'hosp', 599 | 'hpw', 600 | 'hr.ms', 601 | 'hr', 602 | 'hregw', 603 | 'hrg', 604 | 'hst', 605 | 'huis.just', 606 | 'huisv.w', 607 | 'huurbl', 608 | 'hv.vn', 609 | 'hw', 610 | 'hyp.w', 611 | 'i.b.s', 612 | 'i.c.m.h', 613 | 'i.c', 614 | 'i.e', 615 | 'i.f.p', 616 | 'i.f', 617 | 'i.g.v', 618 | 'i.h.a', 619 | 'i.h.b', 620 | 'i.h', 621 | 'i.l.pr', 622 | 'i.o', 623 | 'i.p.o', 624 | 'i.p.r', 625 | 'i.p.v', 626 | 'i.pl.v', 627 | 'i.r.d.i', 628 | 'i.s.m', 629 | 'i.t.t', 630 | 'i.v.m', 631 | 'i.v.s', 632 | 'i.v', 633 | 'i.w.tr', 634 | 'i.z', 635 | 'ib', 636 | 'ibid', 637 | 'icip-ing.cons', 638 | 'iem', 639 | 'ind prop', 640 | 'ind', 641 | 'indic.soc', 642 | 'indiv', 643 | 'inf.i.d.a.c', 644 | 'inf.idac', 645 | 'inf.r.i.z.i.v', 646 | 'inf.riziv', 647 | 'inf.soc.secr', 648 | 'inf', 649 | 'ing.cons', 650 | 'ing', 651 | 'inst', 652 | "int'l & comp.l.q.", 653 | 'int', 654 | 'interm', 655 | 'intern.fisc.act', 656 | 'intern.vervoerr', 657 | 'inv.w', 658 | 'inv.wet', 659 | 'inv', 660 | 'invord.w', 661 | 'inz', 662 | 'ir', 663 | 'irspr', 664 | 'it', 665 | 'iwtr', 666 | 'j.-cl', 667 | 'j.c.b', 668 | 'j.c.e', 669 | 'j.c.fl', 670 | 'j.c.j', 671 | 'j.c.p', 672 | 'j.d.e', 673 | 'j.d.f', 674 | 'j.d.s.c', 675 | 'j.dr.jeun', 676 | 'j.j.d', 677 | 'j.j.p', 678 | 'j.j.pol', 679 | 'j.l.m.b', 680 | 'j.l.o', 681 | 'j.l', 682 | 'j.ordre pharm', 683 | 'j.p.a', 684 | 'j.r.s', 685 | 'j.t.d.e', 686 | 'j.t.dr.eur', 687 | 'j.t.o', 688 | 'j.t.t', 689 | 'j.t', 690 | 'j', 691 | 'jaarl', 692 | 'jb.hand', 693 | 'jb.kred.c.s', 694 | 'jb.kred', 695 | 'jb.l.r.b', 696 | 'jb.lrb', 697 | 'jb.markt', 698 | 'jb.mens', 699 | 'jb.t.r.d', 700 | 'jb.trd', 701 | 'jeugdrb', 702 | 'jeugdwerkg.w', 703 | 'jg', 704 | 'jis', 705 | 'jl', 706 | 'journ.jur', 707 | 'journ.prat.dr.fisc.fin', 708 | 'journ.proc', 709 | 'jrg', 710 | 'jur.comm.fl', 711 | 'jur.dr.soc.b.l.n', 712 | 'jur.f.p.e', 713 | 'jur.fpe', 714 | 'jur.niv', 715 | 'jur.trav.brux', 716 | 'jur', 717 | 'jura falc', 718 | 'jurambt', 719 | 'jv.cass', 720 | 'jv.h.r.j', 721 | 'jv.hrj', 722 | 'jw', 723 | 'k.b', 724 | 'k.g', 725 | 'k.k', 726 | 'k.m.b.o', 727 | 'k.o.o', 728 | 'k.v.k', 729 | 'k.v.v.v', 730 | 'k', 731 | 'kadasterw', 732 | 'kaderb', 733 | 'kador', 734 | 'kbo-nr', 735 | 'kg', 736 | 'kh', 737 | 'kiesw', 738 | 'kind.bes.v', 739 | 'kkr', 740 | 'koopv', 741 | 'kr', 742 | 'krankz.w', 743 | 'ksbel', 744 | 'kt', 745 | 'ktg', 746 | 'ktr', 747 | 'kvdm', 748 | 'kw.r', 749 | 'kymr', 750 | 'kzr', 751 | 'kzw', 752 | 'l.b.o', 753 | 'l.b', 754 | 'l.bas', 755 | 'l.c', 756 | 'l.gew', 757 | 'l.j', 758 | 'l.k', 759 | 'l.l', 760 | 'l.o', 761 | 'l.r.b', 762 | 'l.u.v.i', 763 | 'l.v.r', 764 | 'l.v.w', 765 | 'l.w', 766 | "l'exp.-compt.b.", 767 | 'l’exp.-compt.b', 768 | 'l', 769 | 'landinr.w', 770 | 'landscrt', 771 | 'larcier cass', 772 | 'lat', 773 | 'law.ed', 774 | 'lett', 775 | 'levensverz', 776 | 'lgrs', 777 | 'lidw', 778 | 'limb.rechtsl', 779 | 'lit', 780 | 'litt', 781 | 'liw', 782 | 'liwet', 783 | 'lk', 784 | 'll.(l.)l.r', 785 | 'll', 786 | 'loonw', 787 | 'losbl', 788 | 'ltd', 789 | 'luchtv.w', 790 | 'luchtv', 791 | 'm.a.v.o', 792 | 'm.a.w', 793 | 'm.b.o', 794 | 'm.b.r', 795 | 'm.b.t', 796 | 'm.b', 797 | 'm.d.g.o', 798 | 'm.e.a.o', 799 | 'm.e.r', 800 | 'm.h.d', 801 | 'm.h', 802 | 'm.i.v', 803 | 'm.j.t', 804 | 'm.k', 805 | 'm.m.a', 806 | 'm.m.h.h', 807 | 'm.m.v', 808 | 'm.m', 809 | 'm.n', 810 | 'm.not.fisc', 811 | 'm.nt', 812 | 'm.o', 813 | 'm.r', 814 | 'm.s.a', 815 | 'm.u.p', 816 | 'm.v.a', 817 | 'm.v.h.n', 818 | 'm.v.t', 819 | 'm.z', 820 | 'm', 821 | 'maatr.teboekgest.luchtv', 822 | 'maced', 823 | 'mand', 824 | 'max', 825 | 'mbl.not', 826 | 'me', 827 | 'med.b.u.f.r', 828 | 'med.bufr', 829 | 'med.vbo', 830 | 'med', 831 | 'meerv', 832 | 'meetbr.w', 833 | 'mém.adm', 834 | 'mgr', 835 | 'mgrs', 836 | 'mhd', 837 | 'mi.verantw', 838 | 'mil.bed', 839 | 'mil.ger', 840 | 'mil', 841 | 'min.j.omz', 842 | 'min.just.circ', 843 | 'min', 844 | 'mitt', 845 | 'mnd', 846 | 'mod', 847 | 'mon', 848 | 'monde ass', 849 | 'mouv.comm', 850 | 'mr', 851 | 'ms', 852 | 'muz', 853 | 'mv', 854 | 'mva ii inv', 855 | 'mva inv', 856 | 'n cont', 857 | 'n.a.g', 858 | 'n.a.v', 859 | 'n.a', 860 | 'n.b', 861 | 'n.c', 862 | 'n.chr', 863 | 'n.d.r', 864 | 'n.d', 865 | 'n.e.a', 866 | 'n.g', 867 | 'n.h.b.c', 868 | 'n.j.b', 869 | 'n.j.w', 870 | 'n.j', 871 | 'n.l', 872 | 'n.m.m', 873 | 'n.m', 874 | 'n.n.b', 875 | 'n.n.g', 876 | 'n.n.k', 877 | 'n.n', 878 | 'n.o.m', 879 | 'n.o.t.k', 880 | 'n.rapp', 881 | 'n.tijd.pol', 882 | 'n.v.d.r', 883 | 'n.v.d.v', 884 | 'n.v.h', 885 | 'n.v.o.b', 886 | 'n.v.t', 887 | 'n.v', 888 | 'n', 889 | 'nat.besch.w', 890 | 'nat.omb', 891 | 'nat.pers', 892 | 'ned.cult.r', 893 | 'neg.verkl', 894 | 'nhd', 895 | 'nieuw arch', 896 | 'njcm-bull', 897 | 'nl', 898 | 'nnd', 899 | 'no', 900 | 'not.fisc.m', 901 | 'not.w', 902 | 'not.wet', 903 | 'not', 904 | 'nr', 905 | 'nrs', 906 | 'nste', 907 | 'nt', 908 | 'numism', 909 | 'o.a', 910 | 'o.b', 911 | 'o.c', 912 | 'o.g.v', 913 | 'o.g', 914 | 'o.i.d', 915 | 'o.i', 916 | 'o.m', 917 | 'o.o.d', 918 | 'o.o.v', 919 | 'o.o', 920 | 'o.p', 921 | 'o.r', 922 | 'o.regl', 923 | 'o.s', 924 | 'o.t.s', 925 | 'o.t.t.t', 926 | 'o.t.t.z', 927 | 'o.t.t', 928 | 'o.tk.t', 929 | 'o.v.t.t', 930 | 'o.v.t', 931 | 'o.v.tk.t', 932 | 'o.v.v', 933 | 'o', 934 | 'ob', 935 | 'obsv', 936 | 'octr.gem.regl', 937 | 'octr.regl', 938 | 'octr', 939 | 'oe', 940 | 'oecd mod', 941 | 'off.pol', 942 | 'ofra', 943 | 'ohd', 944 | 'omb', 945 | 'omnia frat', 946 | 'omnil', 947 | 'omz', 948 | 'on.ww', 949 | 'onderr', 950 | 'onfrank', 951 | 'onteig.w', 952 | 'ontw', 953 | 'onuitg', 954 | 'onz', 955 | 'oorl.w', 956 | 'op.cit', 957 | 'opin.pa', 958 | 'opm', 959 | 'or', 960 | 'ord.br', 961 | 'ord.gem', 962 | 'ors', 963 | 'orth', 964 | 'os', 965 | 'osm', 966 | 'ov.w.i', 967 | 'ov.w.ii', 968 | 'ov.ww', 969 | 'ov', 970 | 'overg.w', 971 | 'overw', 972 | 'ovkst', 973 | 'ow kadasterw', 974 | 'oz', 975 | 'p.& b', 976 | 'p.a.o', 977 | 'p.a', 978 | 'p.b.o', 979 | 'p.e', 980 | 'p.g', 981 | 'p.j', 982 | 'p.m.a', 983 | 'p.m', 984 | 'p.o.j.t', 985 | 'p.o', 986 | 'p.p', 987 | 'p.v.s', 988 | 'p.v', 989 | 'p', 990 | 'pachtw', 991 | 'pag', 992 | 'pan', 993 | 'pand.b', 994 | 'pand.pér', 995 | 'parl.gesch', 996 | 'parl.st', 997 | 'parl', 998 | 'part.arb', 999 | 'pas', 1000 | 'pasin', 1001 | 'pat', 1002 | 'pb.c', 1003 | 'pb.l', 1004 | 'pens', 1005 | 'pensioenverz', 1006 | 'per.ber.i.b.r', 1007 | 'per.ber.ibr', 1008 | 'pers', 1009 | 'pft', 1010 | 'pg wijz.rv', 1011 | 'pk', 1012 | 'pktg', 1013 | 'pli jur', 1014 | 'plv', 1015 | 'po', 1016 | 'pol.off', 1017 | 'pol.r', 1018 | 'pol.w', 1019 | 'pol', 1020 | 'politie j', 1021 | 'postbankw', 1022 | 'postw', 1023 | 'pp', 1024 | 'pr', 1025 | 'preadv', 1026 | 'pres', 1027 | 'prf', 1028 | 'prft', 1029 | 'prg', 1030 | 'prijz.w', 1031 | 'pro jus', 1032 | 'proc', 1033 | 'procesregl', 1034 | 'prof', 1035 | 'prot', 1036 | 'prov.b', 1037 | 'prov.instr.h.m.g', 1038 | 'prov.regl', 1039 | 'prov.verord', 1040 | 'prov.w', 1041 | 'prov', 1042 | 'publ.cour eur.d.h', 1043 | 'publ.eur.court h.r', 1044 | 'publ', 1045 | 'pun', 1046 | 'pw', 1047 | 'q.b.d', 1048 | 'q.e.d', 1049 | 'q.q', 1050 | 'q.r', 1051 | 'r.a.b.g', 1052 | 'r.a.c.e', 1053 | 'r.a.j.b', 1054 | 'r.b.d.c', 1055 | 'r.b.d.i', 1056 | 'r.b.s.s', 1057 | 'r.c.b', 1058 | 'r.c.d.c', 1059 | 'r.c.j.b', 1060 | 'r.c.s.j', 1061 | 'r.c', 1062 | 'r.cass', 1063 | 'r.d.c', 1064 | 'r.d.i.d.c', 1065 | 'r.d.i', 1066 | 'r.d.j.b', 1067 | 'r.d.j.p', 1068 | 'r.d.p.c', 1069 | 'r.d.s', 1070 | 'r.d.t.i', 1071 | 'r.e', 1072 | 'r.f.s.v.p', 1073 | 'r.g.a.r', 1074 | 'r.g.c.f', 1075 | 'r.g.d.c', 1076 | 'r.g.f', 1077 | 'r.g.z', 1078 | 'r.h.a', 1079 | 'r.i.c', 1080 | 'r.i.d.a', 1081 | 'r.i.e.j', 1082 | 'r.i.n', 1083 | 'r.i.s.a', 1084 | 'r.j.d.a', 1085 | 'r.j.i', 1086 | 'r.k', 1087 | 'r.l.g.b', 1088 | 'r.l', 1089 | 'r.med.rechtspr', 1090 | 'r.med', 1091 | 'r.n.b', 1092 | 'r.o', 1093 | 'r.orde apoth', 1094 | 'r.ov', 1095 | 'r.p.d.b', 1096 | 'r.p.o.t', 1097 | 'r.p.r.j', 1098 | 'r.p.s', 1099 | 'r.p', 1100 | 'r.r.d', 1101 | 'r.r.s', 1102 | 'r.s.v.p', 1103 | 'r.s', 1104 | 'r.stvb', 1105 | 'r.t.d.f', 1106 | 'r.t.d.h', 1107 | 'r.t.l', 1108 | 'r.trim.dr.eur', 1109 | 'r.v.a', 1110 | 'r.v.k', 1111 | 'r.verkb', 1112 | 'r.w.d', 1113 | 'r.w', 1114 | 'r', 1115 | 'rap.ann.c.a', 1116 | 'rap.ann.c.c', 1117 | 'rap.ann.c.e', 1118 | 'rap.ann.c.s.j', 1119 | 'rap.ann.ca', 1120 | 'rap.ann.cass', 1121 | 'rap.ann.cc', 1122 | 'rap.ann.ce', 1123 | 'rap.ann.csj', 1124 | 'rapp', 1125 | 'rb.kh', 1126 | 'rb.van kh', 1127 | 'rb', 1128 | 'rdn', 1129 | 'rdnr', 1130 | 're.pers', 1131 | 'rec.c.i.j', 1132 | 'rec.c.j.c.e', 1133 | 'rec.cij', 1134 | 'rec.cjce', 1135 | 'rec.cour eur.d.h', 1136 | 'rec.gén.enr.not', 1137 | 'rec.lois decr.arr', 1138 | 'rec', 1139 | 'rechtsh', 1140 | 'rechtsk.t', 1141 | 'rechtspl.zeem', 1142 | 'rechtspr.arb.br', 1143 | 'rechtspr.b.f.e', 1144 | 'rechtspr.bfe', 1145 | 'rechtspr.soc.r.b.l.n', 1146 | 'recl.reg', 1147 | 'rect', 1148 | 'red', 1149 | 'reg.huiz.bew', 1150 | 'reg.w', 1151 | 'reg', 1152 | 'registr.w', 1153 | 'regl.besl', 1154 | 'regl.onderr', 1155 | 'regl.r.t', 1156 | 'regl', 1157 | 'rep.eur.court h.r', 1158 | 'rép.fisc', 1159 | 'rép.not', 1160 | 'rep.r.j', 1161 | 'rep.rj', 1162 | 'rep', 1163 | 'req', 1164 | 'res', 1165 | 'resp', 1166 | 'rev.acc.trav', 1167 | 'rev.adm', 1168 | 'rev.b.compt', 1169 | 'rev.b.dr.const', 1170 | 'rev.b.dr.intern', 1171 | 'rev.b.séc.soc', 1172 | 'rev.banc.fin', 1173 | 'rev.comm', 1174 | 'rev.cons.prud', 1175 | 'rev.dr.b', 1176 | 'rev.dr.commun', 1177 | 'rev.dr.étr', 1178 | 'rev.dr.fam', 1179 | 'rev.dr.intern.comp', 1180 | 'rev.dr.mil', 1181 | 'rev.dr.min', 1182 | 'rev.dr.pén.mil', 1183 | 'rev.dr.pén', 1184 | 'rev.dr.rur', 1185 | 'rev.dr.u.l.b', 1186 | 'rev.dr.ulb', 1187 | 'rev.exp', 1188 | 'rev.faill', 1189 | 'rev.fisc', 1190 | 'rev.gd', 1191 | 'rev.hist.dr', 1192 | 'rev.i.p.c', 1193 | 'rev.ipc', 1194 | 'rev.not.b', 1195 | 'rev.prat.dr.comm', 1196 | 'rev.prat.not.b', 1197 | 'rev.prat.soc', 1198 | 'rev.rec', 1199 | 'rev.rw', 1200 | 'rev.trav', 1201 | 'rev.trim.d.h', 1202 | 'rev.trim.dr.fam', 1203 | 'rev.urb', 1204 | 'rev', 1205 | 'rh', 1206 | 'richtl', 1207 | 'riv.dir.int.priv.proc', 1208 | 'riv.dir.int', 1209 | 'rk', 1210 | 'rln', 1211 | 'roln', 1212 | 'rom', 1213 | 'rondz', 1214 | 'rov', 1215 | 'rprt', 1216 | 'rtl', 1217 | 'rubr', 1218 | 'ruilv.wet', 1219 | 'rv.verdr', 1220 | 'rvkb', 1221 | 's.a', 1222 | 's.b.n', 1223 | 's.ct', 1224 | 's.d', 1225 | 's.e.c', 1226 | 's.e.et.o', 1227 | 's.e.w', 1228 | 's.exec.rept', 1229 | 's.hrg', 1230 | 's.j.b', 1231 | 's.l.e.a', 1232 | 's.l.n.d', 1233 | 's.l', 1234 | 's.p.a', 1235 | 's.s', 1236 | 's.t.b', 1237 | 's.t', 1238 | 's.v.p', 1239 | 's.v', 1240 | 's', 1241 | 'samenw', 1242 | 'sc', 1243 | 'sch', 1244 | 'scheidsr.uitspr', 1245 | 'schepel.besl', 1246 | 'secr.comm', 1247 | 'secr.gen', 1248 | 'sect.soc', 1249 | 'sess', 1250 | 'sir', 1251 | 'soc.act', 1252 | 'soc.best', 1253 | 'soc.kron', 1254 | 'soc.r', 1255 | 'soc.sw', 1256 | 'soc.weg', 1257 | 'soc', 1258 | 'sofi-nr', 1259 | 'somm.ann', 1260 | 'somm', 1261 | 'sp.c.c', 1262 | 'sr', 1263 | 'ss', 1264 | 'st.doc.b.c.n.a.r', 1265 | 'st.doc.bcnar', 1266 | 'st.vw', 1267 | 'st', 1268 | 'stagever', 1269 | 'stas', 1270 | 'stat', 1271 | 'stb', 1272 | 'stbl', 1273 | 'stcrt', 1274 | 'stichting i.v', 1275 | 'strafz', 1276 | 'stud.dipl', 1277 | 'su', 1278 | 'subs', 1279 | 'subst', 1280 | 'succ.w', 1281 | 'suppl', 1282 | 'sv', 1283 | 'sw', 1284 | 't.a.a', 1285 | 't.a.n', 1286 | 't.a.p', 1287 | 't.a.s.n', 1288 | 't.a.v.w', 1289 | 't.a.v', 1290 | 't.a', 1291 | 't.aann', 1292 | 't.acc', 1293 | 't.agr.r', 1294 | 't.app', 1295 | 't.b.b.r', 1296 | 't.b.h', 1297 | 't.b.m', 1298 | 't.b.o', 1299 | 't.b.p', 1300 | 't.b.r', 1301 | 't.b.s', 1302 | 't.b.v', 1303 | 't.bankw', 1304 | 't.belg.not', 1305 | 't.desk', 1306 | 't.e.m', 1307 | 't.e.p', 1308 | 't.f.r', 1309 | 't.fam', 1310 | 't.fin.r', 1311 | 't.g.r', 1312 | 't.g.t', 1313 | 't.g.v', 1314 | 't.gem', 1315 | 't.gez', 1316 | 't.huur', 1317 | 't.i.n', 1318 | 't.in b.z', 1319 | 't.j.k', 1320 | 't.l.l', 1321 | 't.l.v', 1322 | 't.m.r', 1323 | 't.m.w', 1324 | 't.m', 1325 | 't.mil.r', 1326 | 't.mil.strafr', 1327 | 't.not', 1328 | 't.o.r.b', 1329 | 't.o.v', 1330 | 't.o', 1331 | 't.ontv', 1332 | 't.orde geneesh', 1333 | 't.p.r', 1334 | 't.pol', 1335 | 't.r.d.& i', 1336 | 't.r.g', 1337 | 't.r.o.s', 1338 | 't.r.v', 1339 | 't.r', 1340 | 't.s.r', 1341 | 't.strafr', 1342 | 't.t', 1343 | 't.u', 1344 | 't.v.c', 1345 | 't.v.g', 1346 | 't.v.m.r', 1347 | 't.v.o', 1348 | 't.v.v.d.b', 1349 | 't.v.v', 1350 | 't.v.w', 1351 | 't.verz', 1352 | 't.vred', 1353 | 't.vreemd', 1354 | 't.w.k', 1355 | 't.w.v.r', 1356 | 't.w.v', 1357 | 't.w', 1358 | 't.wrr', 1359 | 't.z.t', 1360 | 't.z.v', 1361 | 't.z', 1362 | 't', 1363 | 'taalk', 1364 | 'tar.burg.z', 1365 | 'td', 1366 | 'techn', 1367 | 'tek.mod', 1368 | 'telecomm', 1369 | 'tijdschr', 1370 | 'toel.st.v.w', 1371 | 'toel', 1372 | 'toep.regl', 1373 | 'toep', 1374 | 'tom', 1375 | 'top', 1376 | 'trans.b', 1377 | 'transp.r', 1378 | 'trav.com.ét.et lég.not', 1379 | 'trb', 1380 | 'trib.civ', 1381 | 'trib.gr.inst', 1382 | 'trib', 1383 | 'trim', 1384 | 'ts', 1385 | 'turnh.rechtsl', 1386 | 'tvpol', 1387 | 'tvpr', 1388 | 'tvrechtsgesch', 1389 | 'tw', 1390 | 'u.a.r', 1391 | 'u.a.v', 1392 | 'u.a', 1393 | 'u.c.c', 1394 | 'u.c', 1395 | 'u.g', 1396 | 'u.p', 1397 | 'u.s.d.c', 1398 | 'u.s', 1399 | 'u', 1400 | 'uitdr', 1401 | 'uitl.w', 1402 | 'uitv.besch.div.b', 1403 | 'uitv.besl.bel.rv', 1404 | 'uitv.besl.l.b', 1405 | 'uitv.besl', 1406 | 'uitv.reg.afd.verm', 1407 | 'uitv.reg.bel.d', 1408 | 'uitv.reg.lb', 1409 | 'uitv.reg.succ.w', 1410 | 'uitv.reg', 1411 | 'univ.verkl', 1412 | 'univ', 1413 | 'v.& f', 1414 | 'v.a.v', 1415 | 'v.a', 1416 | 'v.b.o', 1417 | 'v.bp prot', 1418 | 'v.c', 1419 | 'v.chr', 1420 | 'v.h', 1421 | 'v.huw.verm', 1422 | 'v.i.o', 1423 | 'v.i', 1424 | 'v.k.a', 1425 | 'v.m', 1426 | 'v.o.f', 1427 | 'v.o.n', 1428 | 'v.onderh.verpl', 1429 | 'v.p', 1430 | 'v.r', 1431 | 'v.s.o', 1432 | 'v.t.t.t', 1433 | 'v.t.t', 1434 | 'v.tk.t', 1435 | 'v.toep.r.vert', 1436 | 'v.v.b', 1437 | 'v.v.g', 1438 | 'v.v.t.t', 1439 | 'v.v.t', 1440 | 'v.v.tk.t', 1441 | 'v.w.b', 1442 | 'v.z.m', 1443 | 'v', 1444 | 'vb.bo', 1445 | 'vb', 1446 | 'vbb', 1447 | 'vc', 1448 | 'vd', 1449 | 'veldw', 1450 | 'ver.k', 1451 | 'ver.verg.gem', 1452 | 'ver', 1453 | 'verbr', 1454 | 'verd', 1455 | 'verdr.v', 1456 | 'verdr', 1457 | 'verdrag benel.i.z', 1458 | 'verenw', 1459 | 'verg.fr.gem', 1460 | 'verg', 1461 | 'verkl.herz.gw', 1462 | 'verkl', 1463 | 'verl', 1464 | 'vern', 1465 | 'verord', 1466 | 'vers.r', 1467 | 'versch', 1468 | 'versl.c.s.w', 1469 | 'versl.csw', 1470 | 'vert', 1471 | 'verv', 1472 | 'verw', 1473 | 'verz.schr', 1474 | 'verz.w', 1475 | 'verz.wett.besl', 1476 | 'verz.wett.decr.besl', 1477 | 'verz', 1478 | 'vgl', 1479 | 'vid', 1480 | 'vigiles jb', 1481 | 'viss.w', 1482 | 'vl.parl', 1483 | 'vl.r', 1484 | 'vl.t.gez', 1485 | 'vl.w.reg', 1486 | 'vl.w.succ', 1487 | 'vlg', 1488 | 'vn', 1489 | 'vnl', 1490 | 'vnw', 1491 | 'vo.bl', 1492 | 'vo', 1493 | 'voegw', 1494 | 'vol', 1495 | 'volg', 1496 | 'volt', 1497 | 'voorl', 1498 | 'voorz', 1499 | 'vord.w', 1500 | 'vorst.d', 1501 | 'vr', 1502 | 'vred', 1503 | 'vrg', 1504 | 'vrijgrs', 1505 | 'vs', 1506 | 'vt', 1507 | 'vvsr jb', 1508 | 'vw', 1509 | 'vz', 1510 | 'vzngr', 1511 | 'vzr', 1512 | 'w.a', 1513 | 'w.b.r', 1514 | 'w.c.h', 1515 | 'w.conf.huw', 1516 | 'w.conf.huwelijksb', 1517 | 'w.consum.kr', 1518 | 'w.f.r', 1519 | 'w.g', 1520 | 'w.gelijke beh', 1521 | 'w.gew.r', 1522 | 'w.ident.pl', 1523 | 'w.just.doc', 1524 | 'w.kh', 1525 | 'w.l.r', 1526 | 'w.l.v', 1527 | 'w.mil.straf.spr', 1528 | 'w.n', 1529 | 'w.not.ambt', 1530 | 'w.o.d.huurcomm', 1531 | 'w.o.d.k', 1532 | 'w.o', 1533 | 'w.openb.manif', 1534 | 'w.parl', 1535 | 'w.r', 1536 | 'w.reg', 1537 | 'w.succ', 1538 | 'w.u.b', 1539 | 'w.uitv.pl.verord', 1540 | 'w.v.k', 1541 | 'w.v.m.s', 1542 | 'w.v.r', 1543 | 'w.v.w', 1544 | 'w.v', 1545 | 'w.venn', 1546 | 'w', 1547 | 'wac', 1548 | 'wd', 1549 | 'wet a.b', 1550 | 'wet bel.rv', 1551 | 'wet c.a.o', 1552 | 'wet c.o', 1553 | 'wet div.bel', 1554 | 'wet ksbel', 1555 | 'wet l.v', 1556 | 'wetb', 1557 | 'wgb', 1558 | 'winkelt.w', 1559 | 'wisk', 1560 | 'wka-verkl', 1561 | 'wnd', 1562 | 'won.w', 1563 | 'woningw', 1564 | 'woonr.w', 1565 | 'wrr.ber', 1566 | 'wrr', 1567 | 'wrsch', 1568 | 'ws', 1569 | 'wsch', 1570 | 'wsr', 1571 | 'wtvb', 1572 | 'ww', 1573 | 'x.d', 1574 | 'z cont', 1575 | 'z.a', 1576 | 'z.g', 1577 | 'z.i', 1578 | 'z.j', 1579 | 'z.o.z', 1580 | 'z.p', 1581 | 'z.s.m', 1582 | 'zesde richtl', 1583 | 'zg', 1584 | 'zgn', 1585 | 'zn', 1586 | 'znw', 1587 | 'zr.ms', 1588 | 'zr' 1589 | 1590 | ]) 1591 | 1592 | export default class Dutch extends BaseLanguage { 1593 | static abbreviations = abbreviations 1594 | } 1595 | --------------------------------------------------------------------------------