speakingurl.js (37421B)
1 (function (root) { 2 'use strict'; 3 4 /** 5 * charMap 6 * @type {Object} 7 */ 8 var charMap = { 9 10 // latin 11 'À': 'A', 12 'Á': 'A', 13 'Â': 'A', 14 'Ã': 'A', 15 'Ä': 'Ae', 16 'Å': 'A', 17 'Æ': 'AE', 18 'Ç': 'C', 19 'È': 'E', 20 'É': 'E', 21 'Ê': 'E', 22 'Ë': 'E', 23 'Ì': 'I', 24 'Í': 'I', 25 'Î': 'I', 26 'Ï': 'I', 27 'Ð': 'D', 28 'Ñ': 'N', 29 'Ò': 'O', 30 'Ó': 'O', 31 'Ô': 'O', 32 'Õ': 'O', 33 'Ö': 'Oe', 34 'Ő': 'O', 35 'Ø': 'O', 36 'Ù': 'U', 37 'Ú': 'U', 38 'Û': 'U', 39 'Ü': 'Ue', 40 'Ű': 'U', 41 'Ý': 'Y', 42 'Þ': 'TH', 43 'ß': 'ss', 44 'à': 'a', 45 'á': 'a', 46 'â': 'a', 47 'ã': 'a', 48 'ä': 'ae', 49 'å': 'a', 50 'æ': 'ae', 51 'ç': 'c', 52 'è': 'e', 53 'é': 'e', 54 'ê': 'e', 55 'ë': 'e', 56 'ì': 'i', 57 'í': 'i', 58 'î': 'i', 59 'ï': 'i', 60 'ð': 'd', 61 'ñ': 'n', 62 'ò': 'o', 63 'ó': 'o', 64 'ô': 'o', 65 'õ': 'o', 66 'ö': 'oe', 67 'ő': 'o', 68 'ø': 'o', 69 'ù': 'u', 70 'ú': 'u', 71 'û': 'u', 72 'ü': 'ue', 73 'ű': 'u', 74 'ý': 'y', 75 'þ': 'th', 76 'ÿ': 'y', 77 'ẞ': 'SS', 78 79 // language specific 80 81 // Arabic 82 'ا': 'a', 83 'أ': 'a', 84 'إ': 'i', 85 'آ': 'aa', 86 'ؤ': 'u', 87 'ئ': 'e', 88 'ء': 'a', 89 'ب': 'b', 90 'ت': 't', 91 'ث': 'th', 92 'ج': 'j', 93 'ح': 'h', 94 'خ': 'kh', 95 'د': 'd', 96 'ذ': 'th', 97 'ر': 'r', 98 'ز': 'z', 99 'س': 's', 100 'ش': 'sh', 101 'ص': 's', 102 'ض': 'dh', 103 'ط': 't', 104 'ظ': 'z', 105 'ع': 'a', 106 'غ': 'gh', 107 'ف': 'f', 108 'ق': 'q', 109 'ك': 'k', 110 'ل': 'l', 111 'م': 'm', 112 'ن': 'n', 113 'ه': 'h', 114 'و': 'w', 115 'ي': 'y', 116 'ى': 'a', 117 'ة': 'h', 118 'ﻻ': 'la', 119 'ﻷ': 'laa', 120 'ﻹ': 'lai', 121 'ﻵ': 'laa', 122 123 // Persian additional characters than Arabic 124 'گ': 'g', 125 'چ': 'ch', 126 'پ': 'p', 127 'ژ': 'zh', 128 'ک': 'k', 129 'ی': 'y', 130 131 // Arabic diactrics 132 'َ': 'a', 133 'ً': 'an', 134 'ِ': 'e', 135 'ٍ': 'en', 136 'ُ': 'u', 137 'ٌ': 'on', 138 'ْ': '', 139 140 // Arabic numbers 141 '٠': '0', 142 '١': '1', 143 '٢': '2', 144 '٣': '3', 145 '٤': '4', 146 '٥': '5', 147 '٦': '6', 148 '٧': '7', 149 '٨': '8', 150 '٩': '9', 151 152 // Persian numbers 153 '۰': '0', 154 '۱': '1', 155 '۲': '2', 156 '۳': '3', 157 '۴': '4', 158 '۵': '5', 159 '۶': '6', 160 '۷': '7', 161 '۸': '8', 162 '۹': '9', 163 164 // Burmese consonants 165 'က': 'k', 166 'ခ': 'kh', 167 'ဂ': 'g', 168 'ဃ': 'ga', 169 'င': 'ng', 170 'စ': 's', 171 'ဆ': 'sa', 172 'ဇ': 'z', 173 'စျ': 'za', 174 'ည': 'ny', 175 'ဋ': 't', 176 'ဌ': 'ta', 177 'ဍ': 'd', 178 'ဎ': 'da', 179 'ဏ': 'na', 180 'တ': 't', 181 'ထ': 'ta', 182 'ဒ': 'd', 183 'ဓ': 'da', 184 'န': 'n', 185 'ပ': 'p', 186 'ဖ': 'pa', 187 'ဗ': 'b', 188 'ဘ': 'ba', 189 'မ': 'm', 190 'ယ': 'y', 191 'ရ': 'ya', 192 'လ': 'l', 193 'ဝ': 'w', 194 'သ': 'th', 195 'ဟ': 'h', 196 'ဠ': 'la', 197 'အ': 'a', 198 // consonant character combos 199 'ြ': 'y', 200 'ျ': 'ya', 201 'ွ': 'w', 202 'ြွ': 'yw', 203 'ျွ': 'ywa', 204 'ှ': 'h', 205 // independent vowels 206 'ဧ': 'e', 207 '၏': '-e', 208 'ဣ': 'i', 209 'ဤ': '-i', 210 'ဉ': 'u', 211 'ဦ': '-u', 212 'ဩ': 'aw', 213 'သြော': 'aw', 214 'ဪ': 'aw', 215 // numbers 216 '၀': '0', 217 '၁': '1', 218 '၂': '2', 219 '၃': '3', 220 '၄': '4', 221 '၅': '5', 222 '၆': '6', 223 '၇': '7', 224 '၈': '8', 225 '၉': '9', 226 // virama and tone marks which are silent in transliteration 227 '္': '', 228 '့': '', 229 'း': '', 230 231 // Czech 232 'č': 'c', 233 'ď': 'd', 234 'ě': 'e', 235 'ň': 'n', 236 'ř': 'r', 237 'š': 's', 238 'ť': 't', 239 'ů': 'u', 240 'ž': 'z', 241 'Č': 'C', 242 'Ď': 'D', 243 'Ě': 'E', 244 'Ň': 'N', 245 'Ř': 'R', 246 'Š': 'S', 247 'Ť': 'T', 248 'Ů': 'U', 249 'Ž': 'Z', 250 251 // Dhivehi 252 'ހ': 'h', 253 'ށ': 'sh', 254 'ނ': 'n', 255 'ރ': 'r', 256 'ބ': 'b', 257 'ޅ': 'lh', 258 'ކ': 'k', 259 'އ': 'a', 260 'ވ': 'v', 261 'މ': 'm', 262 'ފ': 'f', 263 'ދ': 'dh', 264 'ތ': 'th', 265 'ލ': 'l', 266 'ގ': 'g', 267 'ޏ': 'gn', 268 'ސ': 's', 269 'ޑ': 'd', 270 'ޒ': 'z', 271 'ޓ': 't', 272 'ޔ': 'y', 273 'ޕ': 'p', 274 'ޖ': 'j', 275 'ޗ': 'ch', 276 'ޘ': 'tt', 277 'ޙ': 'hh', 278 'ޚ': 'kh', 279 'ޛ': 'th', 280 'ޜ': 'z', 281 'ޝ': 'sh', 282 'ޞ': 's', 283 'ޟ': 'd', 284 'ޠ': 't', 285 'ޡ': 'z', 286 'ޢ': 'a', 287 'ޣ': 'gh', 288 'ޤ': 'q', 289 'ޥ': 'w', 290 'ަ': 'a', 291 'ާ': 'aa', 292 'ި': 'i', 293 'ީ': 'ee', 294 'ު': 'u', 295 'ޫ': 'oo', 296 'ެ': 'e', 297 'ޭ': 'ey', 298 'ޮ': 'o', 299 'ޯ': 'oa', 300 'ް': '', 301 302 // Georgian https://en.wikipedia.org/wiki/Romanization_of_Georgian 303 // National system (2002) 304 'ა': 'a', 305 'ბ': 'b', 306 'გ': 'g', 307 'დ': 'd', 308 'ე': 'e', 309 'ვ': 'v', 310 'ზ': 'z', 311 'თ': 't', 312 'ი': 'i', 313 'კ': 'k', 314 'ლ': 'l', 315 'მ': 'm', 316 'ნ': 'n', 317 'ო': 'o', 318 'პ': 'p', 319 'ჟ': 'zh', 320 'რ': 'r', 321 'ს': 's', 322 'ტ': 't', 323 'უ': 'u', 324 'ფ': 'p', 325 'ქ': 'k', 326 'ღ': 'gh', 327 'ყ': 'q', 328 'შ': 'sh', 329 'ჩ': 'ch', 330 'ც': 'ts', 331 'ძ': 'dz', 332 'წ': 'ts', 333 'ჭ': 'ch', 334 'ხ': 'kh', 335 'ჯ': 'j', 336 'ჰ': 'h', 337 338 // Greek 339 'α': 'a', 340 'β': 'v', 341 'γ': 'g', 342 'δ': 'd', 343 'ε': 'e', 344 'ζ': 'z', 345 'η': 'i', 346 'θ': 'th', 347 'ι': 'i', 348 'κ': 'k', 349 'λ': 'l', 350 'μ': 'm', 351 'ν': 'n', 352 'ξ': 'ks', 353 'ο': 'o', 354 'π': 'p', 355 'ρ': 'r', 356 'σ': 's', 357 'τ': 't', 358 'υ': 'y', 359 'φ': 'f', 360 'χ': 'x', 361 'ψ': 'ps', 362 'ω': 'o', 363 'ά': 'a', 364 'έ': 'e', 365 'ί': 'i', 366 'ό': 'o', 367 'ύ': 'y', 368 'ή': 'i', 369 'ώ': 'o', 370 'ς': 's', 371 'ϊ': 'i', 372 'ΰ': 'y', 373 'ϋ': 'y', 374 'ΐ': 'i', 375 'Α': 'A', 376 'Β': 'B', 377 'Γ': 'G', 378 'Δ': 'D', 379 'Ε': 'E', 380 'Ζ': 'Z', 381 'Η': 'I', 382 'Θ': 'TH', 383 'Ι': 'I', 384 'Κ': 'K', 385 'Λ': 'L', 386 'Μ': 'M', 387 'Ν': 'N', 388 'Ξ': 'KS', 389 'Ο': 'O', 390 'Π': 'P', 391 'Ρ': 'R', 392 'Σ': 'S', 393 'Τ': 'T', 394 'Υ': 'Y', 395 'Φ': 'F', 396 'Χ': 'X', 397 'Ψ': 'PS', 398 'Ω': 'O', 399 'Ά': 'A', 400 'Έ': 'E', 401 'Ί': 'I', 402 'Ό': 'O', 403 'Ύ': 'Y', 404 'Ή': 'I', 405 'Ώ': 'O', 406 'Ϊ': 'I', 407 'Ϋ': 'Y', 408 409 // Latvian 410 'ā': 'a', 411 // 'č': 'c', // duplicate 412 'ē': 'e', 413 'ģ': 'g', 414 'ī': 'i', 415 'ķ': 'k', 416 'ļ': 'l', 417 'ņ': 'n', 418 // 'š': 's', // duplicate 419 'ū': 'u', 420 // 'ž': 'z', // duplicate 421 'Ā': 'A', 422 // 'Č': 'C', // duplicate 423 'Ē': 'E', 424 'Ģ': 'G', 425 'Ī': 'I', 426 'Ķ': 'k', 427 'Ļ': 'L', 428 'Ņ': 'N', 429 // 'Š': 'S', // duplicate 430 'Ū': 'U', 431 // 'Ž': 'Z', // duplicate 432 433 // Macedonian 434 'Ќ': 'Kj', 435 'ќ': 'kj', 436 'Љ': 'Lj', 437 'љ': 'lj', 438 'Њ': 'Nj', 439 'њ': 'nj', 440 'Тс': 'Ts', 441 'тс': 'ts', 442 443 // Polish 444 'ą': 'a', 445 'ć': 'c', 446 'ę': 'e', 447 'ł': 'l', 448 'ń': 'n', 449 // 'ó': 'o', // duplicate 450 'ś': 's', 451 'ź': 'z', 452 'ż': 'z', 453 'Ą': 'A', 454 'Ć': 'C', 455 'Ę': 'E', 456 'Ł': 'L', 457 'Ń': 'N', 458 'Ś': 'S', 459 'Ź': 'Z', 460 'Ż': 'Z', 461 462 // Ukranian 463 'Є': 'Ye', 464 'І': 'I', 465 'Ї': 'Yi', 466 'Ґ': 'G', 467 'є': 'ye', 468 'і': 'i', 469 'ї': 'yi', 470 'ґ': 'g', 471 472 // Romanian 473 'ă': 'a', 474 'Ă': 'A', 475 'ș': 's', 476 'Ș': 'S', 477 // 'ş': 's', // duplicate 478 // 'Ş': 'S', // duplicate 479 'ț': 't', 480 'Ț': 'T', 481 'ţ': 't', 482 'Ţ': 'T', 483 484 // Russian https://en.wikipedia.org/wiki/Romanization_of_Russian 485 // ICAO 486 487 'а': 'a', 488 'б': 'b', 489 'в': 'v', 490 'г': 'g', 491 'д': 'd', 492 'е': 'e', 493 'ё': 'yo', 494 'ж': 'zh', 495 'з': 'z', 496 'и': 'i', 497 'й': 'i', 498 'к': 'k', 499 'л': 'l', 500 'м': 'm', 501 'н': 'n', 502 'о': 'o', 503 'п': 'p', 504 'р': 'r', 505 'с': 's', 506 'т': 't', 507 'у': 'u', 508 'ф': 'f', 509 'х': 'kh', 510 'ц': 'c', 511 'ч': 'ch', 512 'ш': 'sh', 513 'щ': 'sh', 514 'ъ': '', 515 'ы': 'y', 516 'ь': '', 517 'э': 'e', 518 'ю': 'yu', 519 'я': 'ya', 520 'А': 'A', 521 'Б': 'B', 522 'В': 'V', 523 'Г': 'G', 524 'Д': 'D', 525 'Е': 'E', 526 'Ё': 'Yo', 527 'Ж': 'Zh', 528 'З': 'Z', 529 'И': 'I', 530 'Й': 'I', 531 'К': 'K', 532 'Л': 'L', 533 'М': 'M', 534 'Н': 'N', 535 'О': 'O', 536 'П': 'P', 537 'Р': 'R', 538 'С': 'S', 539 'Т': 'T', 540 'У': 'U', 541 'Ф': 'F', 542 'Х': 'Kh', 543 'Ц': 'C', 544 'Ч': 'Ch', 545 'Ш': 'Sh', 546 'Щ': 'Sh', 547 'Ъ': '', 548 'Ы': 'Y', 549 'Ь': '', 550 'Э': 'E', 551 'Ю': 'Yu', 552 'Я': 'Ya', 553 554 // Serbian 555 'ђ': 'dj', 556 'ј': 'j', 557 // 'љ': 'lj', // duplicate 558 // 'њ': 'nj', // duplicate 559 'ћ': 'c', 560 'џ': 'dz', 561 'Ђ': 'Dj', 562 'Ј': 'j', 563 // 'Љ': 'Lj', // duplicate 564 // 'Њ': 'Nj', // duplicate 565 'Ћ': 'C', 566 'Џ': 'Dz', 567 568 // Slovak 569 'ľ': 'l', 570 'ĺ': 'l', 571 'ŕ': 'r', 572 'Ľ': 'L', 573 'Ĺ': 'L', 574 'Ŕ': 'R', 575 576 // Turkish 577 'ş': 's', 578 'Ş': 'S', 579 'ı': 'i', 580 'İ': 'I', 581 // 'ç': 'c', // duplicate 582 // 'Ç': 'C', // duplicate 583 // 'ü': 'u', // duplicate, see langCharMap 584 // 'Ü': 'U', // duplicate, see langCharMap 585 // 'ö': 'o', // duplicate, see langCharMap 586 // 'Ö': 'O', // duplicate, see langCharMap 587 'ğ': 'g', 588 'Ğ': 'G', 589 590 // Vietnamese 591 'ả': 'a', 592 'Ả': 'A', 593 'ẳ': 'a', 594 'Ẳ': 'A', 595 'ẩ': 'a', 596 'Ẩ': 'A', 597 'đ': 'd', 598 'Đ': 'D', 599 'ẹ': 'e', 600 'Ẹ': 'E', 601 'ẽ': 'e', 602 'Ẽ': 'E', 603 'ẻ': 'e', 604 'Ẻ': 'E', 605 'ế': 'e', 606 'Ế': 'E', 607 'ề': 'e', 608 'Ề': 'E', 609 'ệ': 'e', 610 'Ệ': 'E', 611 'ễ': 'e', 612 'Ễ': 'E', 613 'ể': 'e', 614 'Ể': 'E', 615 'ỏ': 'o', 616 'ọ': 'o', 617 'Ọ': 'o', 618 'ố': 'o', 619 'Ố': 'O', 620 'ồ': 'o', 621 'Ồ': 'O', 622 'ổ': 'o', 623 'Ổ': 'O', 624 'ộ': 'o', 625 'Ộ': 'O', 626 'ỗ': 'o', 627 'Ỗ': 'O', 628 'ơ': 'o', 629 'Ơ': 'O', 630 'ớ': 'o', 631 'Ớ': 'O', 632 'ờ': 'o', 633 'Ờ': 'O', 634 'ợ': 'o', 635 'Ợ': 'O', 636 'ỡ': 'o', 637 'Ỡ': 'O', 638 'Ở': 'o', 639 'ở': 'o', 640 'ị': 'i', 641 'Ị': 'I', 642 'ĩ': 'i', 643 'Ĩ': 'I', 644 'ỉ': 'i', 645 'Ỉ': 'i', 646 'ủ': 'u', 647 'Ủ': 'U', 648 'ụ': 'u', 649 'Ụ': 'U', 650 'ũ': 'u', 651 'Ũ': 'U', 652 'ư': 'u', 653 'Ư': 'U', 654 'ứ': 'u', 655 'Ứ': 'U', 656 'ừ': 'u', 657 'Ừ': 'U', 658 'ự': 'u', 659 'Ự': 'U', 660 'ữ': 'u', 661 'Ữ': 'U', 662 'ử': 'u', 663 'Ử': 'ư', 664 'ỷ': 'y', 665 'Ỷ': 'y', 666 'ỳ': 'y', 667 'Ỳ': 'Y', 668 'ỵ': 'y', 669 'Ỵ': 'Y', 670 'ỹ': 'y', 671 'Ỹ': 'Y', 672 'ạ': 'a', 673 'Ạ': 'A', 674 'ấ': 'a', 675 'Ấ': 'A', 676 'ầ': 'a', 677 'Ầ': 'A', 678 'ậ': 'a', 679 'Ậ': 'A', 680 'ẫ': 'a', 681 'Ẫ': 'A', 682 // 'ă': 'a', // duplicate 683 // 'Ă': 'A', // duplicate 684 'ắ': 'a', 685 'Ắ': 'A', 686 'ằ': 'a', 687 'Ằ': 'A', 688 'ặ': 'a', 689 'Ặ': 'A', 690 'ẵ': 'a', 691 'Ẵ': 'A', 692 693 // symbols 694 '“': '"', 695 '”': '"', 696 '‘': "'", 697 '’': "'", 698 '∂': 'd', 699 'ƒ': 'f', 700 '™': '(TM)', 701 '©': '(C)', 702 'œ': 'oe', 703 'Œ': 'OE', 704 '®': '(R)', 705 '†': '+', 706 '℠': '(SM)', 707 '…': '...', 708 '˚': 'o', 709 'º': 'o', 710 'ª': 'a', 711 '•': '*', 712 '၊': ',', 713 '။': '.', 714 715 // currency 716 '$': 'USD', 717 '€': 'EUR', 718 '₢': 'BRN', 719 '₣': 'FRF', 720 '£': 'GBP', 721 '₤': 'ITL', 722 '₦': 'NGN', 723 '₧': 'ESP', 724 '₩': 'KRW', 725 '₪': 'ILS', 726 '₫': 'VND', 727 '₭': 'LAK', 728 '₮': 'MNT', 729 '₯': 'GRD', 730 '₱': 'ARS', 731 '₲': 'PYG', 732 '₳': 'ARA', 733 '₴': 'UAH', 734 '₵': 'GHS', 735 '¢': 'cent', 736 '¥': 'CNY', 737 '元': 'CNY', 738 '円': 'YEN', 739 '﷼': 'IRR', 740 '₠': 'EWE', 741 '฿': 'THB', 742 '₨': 'INR', 743 '₹': 'INR', 744 '₰': 'PF', 745 '₺': 'TRY', 746 '؋': 'AFN', 747 '₼': 'AZN', 748 'лв': 'BGN', 749 '៛': 'KHR', 750 '₡': 'CRC', 751 '₸': 'KZT', 752 'ден': 'MKD', 753 'zł': 'PLN', 754 '₽': 'RUB', 755 '₾': 'GEL' 756 757 }; 758 759 /** 760 * special look ahead character array 761 * These characters form with consonants to become 'single'/consonant combo 762 * @type [Array] 763 */ 764 var lookAheadCharArray = [ 765 // burmese 766 '်', 767 768 // Dhivehi 769 'ް' 770 ]; 771 772 /** 773 * diatricMap for languages where transliteration changes entirely as more diatrics are added 774 * @type {Object} 775 */ 776 var diatricMap = { 777 // Burmese 778 // dependent vowels 779 'ာ': 'a', 780 'ါ': 'a', 781 'ေ': 'e', 782 'ဲ': 'e', 783 'ိ': 'i', 784 'ီ': 'i', 785 'ို': 'o', 786 'ု': 'u', 787 'ူ': 'u', 788 'ေါင်': 'aung', 789 'ော': 'aw', 790 'ော်': 'aw', 791 'ေါ': 'aw', 792 'ေါ်': 'aw', 793 '်': '်', // this is special case but the character will be converted to latin in the code 794 'က်': 'et', 795 'ိုက်': 'aik', 796 'ောက်': 'auk', 797 'င်': 'in', 798 'ိုင်': 'aing', 799 'ောင်': 'aung', 800 'စ်': 'it', 801 'ည်': 'i', 802 'တ်': 'at', 803 'ိတ်': 'eik', 804 'ုတ်': 'ok', 805 'ွတ်': 'ut', 806 'ေတ်': 'it', 807 'ဒ်': 'd', 808 'ိုဒ်': 'ok', 809 'ုဒ်': 'ait', 810 'န်': 'an', 811 'ာန်': 'an', 812 'ိန်': 'ein', 813 'ုန်': 'on', 814 'ွန်': 'un', 815 'ပ်': 'at', 816 'ိပ်': 'eik', 817 'ုပ်': 'ok', 818 'ွပ်': 'ut', 819 'န်ုပ်': 'nub', 820 'မ်': 'an', 821 'ိမ်': 'ein', 822 'ုမ်': 'on', 823 'ွမ်': 'un', 824 'ယ်': 'e', 825 'ိုလ်': 'ol', 826 'ဉ်': 'in', 827 'ံ': 'an', 828 'ိံ': 'ein', 829 'ုံ': 'on', 830 831 // Dhivehi 832 'ައް': 'ah', 833 'ަށް': 'ah' 834 }; 835 836 /** 837 * langCharMap language specific characters translations 838 * @type {Object} 839 */ 840 var langCharMap = { 841 'en': {}, // default language 842 843 'az': { // Azerbaijani 844 'ç': 'c', 845 'ə': 'e', 846 'ğ': 'g', 847 'ı': 'i', 848 'ö': 'o', 849 'ş': 's', 850 'ü': 'u', 851 'Ç': 'C', 852 'Ə': 'E', 853 'Ğ': 'G', 854 'İ': 'I', 855 'Ö': 'O', 856 'Ş': 'S', 857 'Ü': 'U' 858 }, 859 860 'cs': { // Czech 861 'č': 'c', 862 'ď': 'd', 863 'ě': 'e', 864 'ň': 'n', 865 'ř': 'r', 866 'š': 's', 867 'ť': 't', 868 'ů': 'u', 869 'ž': 'z', 870 'Č': 'C', 871 'Ď': 'D', 872 'Ě': 'E', 873 'Ň': 'N', 874 'Ř': 'R', 875 'Š': 'S', 876 'Ť': 'T', 877 'Ů': 'U', 878 'Ž': 'Z' 879 }, 880 881 'fi': { // Finnish 882 // 'å': 'a', duplicate see charMap/latin 883 // 'Å': 'A', duplicate see charMap/latin 884 'ä': 'a', // ok 885 'Ä': 'A', // ok 886 'ö': 'o', // ok 887 'Ö': 'O' // ok 888 }, 889 890 'hu': { // Hungarian 891 'ä': 'a', // ok 892 'Ä': 'A', // ok 893 // 'á': 'a', duplicate see charMap/latin 894 // 'Á': 'A', duplicate see charMap/latin 895 'ö': 'o', // ok 896 'Ö': 'O', // ok 897 // 'ő': 'o', duplicate see charMap/latin 898 // 'Ő': 'O', duplicate see charMap/latin 899 'ü': 'u', 900 'Ü': 'U', 901 'ű': 'u', 902 'Ű': 'U' 903 }, 904 905 'lt': { // Lithuanian 906 'ą': 'a', 907 'č': 'c', 908 'ę': 'e', 909 'ė': 'e', 910 'į': 'i', 911 'š': 's', 912 'ų': 'u', 913 'ū': 'u', 914 'ž': 'z', 915 'Ą': 'A', 916 'Č': 'C', 917 'Ę': 'E', 918 'Ė': 'E', 919 'Į': 'I', 920 'Š': 'S', 921 'Ų': 'U', 922 'Ū': 'U' 923 }, 924 925 'lv': { // Latvian 926 'ā': 'a', 927 'č': 'c', 928 'ē': 'e', 929 'ģ': 'g', 930 'ī': 'i', 931 'ķ': 'k', 932 'ļ': 'l', 933 'ņ': 'n', 934 'š': 's', 935 'ū': 'u', 936 'ž': 'z', 937 'Ā': 'A', 938 'Č': 'C', 939 'Ē': 'E', 940 'Ģ': 'G', 941 'Ī': 'i', 942 'Ķ': 'k', 943 'Ļ': 'L', 944 'Ņ': 'N', 945 'Š': 'S', 946 'Ū': 'u', 947 'Ž': 'Z' 948 }, 949 950 'pl': { // Polish 951 'ą': 'a', 952 'ć': 'c', 953 'ę': 'e', 954 'ł': 'l', 955 'ń': 'n', 956 'ó': 'o', 957 'ś': 's', 958 'ź': 'z', 959 'ż': 'z', 960 'Ą': 'A', 961 'Ć': 'C', 962 'Ę': 'e', 963 'Ł': 'L', 964 'Ń': 'N', 965 'Ó': 'O', 966 'Ś': 'S', 967 'Ź': 'Z', 968 'Ż': 'Z' 969 }, 970 971 'sk': { // Slovak 972 'ä': 'a', 973 'Ä': 'A' 974 }, 975 976 'sr': { // Serbian 977 'љ': 'lj', 978 'њ': 'nj', 979 'Љ': 'Lj', 980 'Њ': 'Nj', 981 'đ': 'dj', 982 'Đ': 'Dj' 983 }, 984 985 'tr': { // Turkish 986 'Ü': 'U', 987 'Ö': 'O', 988 'ü': 'u', 989 'ö': 'o' 990 } 991 }; 992 993 /** 994 * symbolMap language specific symbol translations 995 * translations must be transliterated already 996 * @type {Object} 997 */ 998 var symbolMap = { 999 'ar': { 1000 '∆': 'delta', 1001 '∞': 'la-nihaya', 1002 '♥': 'hob', 1003 '&': 'wa', 1004 '|': 'aw', 1005 '<': 'aqal-men', 1006 '>': 'akbar-men', 1007 '∑': 'majmou', 1008 '¤': 'omla' 1009 }, 1010 1011 'az': {}, 1012 1013 'ca': { 1014 '∆': 'delta', 1015 '∞': 'infinit', 1016 '♥': 'amor', 1017 '&': 'i', 1018 '|': 'o', 1019 '<': 'menys que', 1020 '>': 'mes que', 1021 '∑': 'suma dels', 1022 '¤': 'moneda' 1023 }, 1024 1025 'cs': { 1026 '∆': 'delta', 1027 '∞': 'nekonecno', 1028 '♥': 'laska', 1029 '&': 'a', 1030 '|': 'nebo', 1031 '<': 'mensi nez', 1032 '>': 'vetsi nez', 1033 '∑': 'soucet', 1034 '¤': 'mena' 1035 }, 1036 1037 'de': { 1038 '∆': 'delta', 1039 '∞': 'unendlich', 1040 '♥': 'Liebe', 1041 '&': 'und', 1042 '|': 'oder', 1043 '<': 'kleiner als', 1044 '>': 'groesser als', 1045 '∑': 'Summe von', 1046 '¤': 'Waehrung' 1047 }, 1048 1049 'dv': { 1050 '∆': 'delta', 1051 '∞': 'kolunulaa', 1052 '♥': 'loabi', 1053 '&': 'aai', 1054 '|': 'noonee', 1055 '<': 'ah vure kuda', 1056 '>': 'ah vure bodu', 1057 '∑': 'jumula', 1058 '¤': 'faisaa' 1059 }, 1060 1061 'en': { 1062 '∆': 'delta', 1063 '∞': 'infinity', 1064 '♥': 'love', 1065 '&': 'and', 1066 '|': 'or', 1067 '<': 'less than', 1068 '>': 'greater than', 1069 '∑': 'sum', 1070 '¤': 'currency' 1071 }, 1072 1073 'es': { 1074 '∆': 'delta', 1075 '∞': 'infinito', 1076 '♥': 'amor', 1077 '&': 'y', 1078 '|': 'u', 1079 '<': 'menos que', 1080 '>': 'mas que', 1081 '∑': 'suma de los', 1082 '¤': 'moneda' 1083 }, 1084 1085 'fa': { 1086 '∆': 'delta', 1087 '∞': 'bi-nahayat', 1088 '♥': 'eshgh', 1089 '&': 'va', 1090 '|': 'ya', 1091 '<': 'kamtar-az', 1092 '>': 'bishtar-az', 1093 '∑': 'majmooe', 1094 '¤': 'vahed' 1095 }, 1096 1097 'fi': { 1098 '∆': 'delta', 1099 '∞': 'aarettomyys', 1100 '♥': 'rakkaus', 1101 '&': 'ja', 1102 '|': 'tai', 1103 '<': 'pienempi kuin', 1104 '>': 'suurempi kuin', 1105 '∑': 'summa', 1106 '¤': 'valuutta' 1107 }, 1108 1109 'fr': { 1110 '∆': 'delta', 1111 '∞': 'infiniment', 1112 '♥': 'Amour', 1113 '&': 'et', 1114 '|': 'ou', 1115 '<': 'moins que', 1116 '>': 'superieure a', 1117 '∑': 'somme des', 1118 '¤': 'monnaie' 1119 }, 1120 1121 'ge': { 1122 '∆': 'delta', 1123 '∞': 'usasruloba', 1124 '♥': 'siqvaruli', 1125 '&': 'da', 1126 '|': 'an', 1127 '<': 'naklebi', 1128 '>': 'meti', 1129 '∑': 'jami', 1130 '¤': 'valuta' 1131 }, 1132 1133 'gr': {}, 1134 1135 'hu': { 1136 '∆': 'delta', 1137 '∞': 'vegtelen', 1138 '♥': 'szerelem', 1139 '&': 'es', 1140 '|': 'vagy', 1141 '<': 'kisebb mint', 1142 '>': 'nagyobb mint', 1143 '∑': 'szumma', 1144 '¤': 'penznem' 1145 }, 1146 1147 'it': { 1148 '∆': 'delta', 1149 '∞': 'infinito', 1150 '♥': 'amore', 1151 '&': 'e', 1152 '|': 'o', 1153 '<': 'minore di', 1154 '>': 'maggiore di', 1155 '∑': 'somma', 1156 '¤': 'moneta' 1157 }, 1158 1159 'lt': { 1160 '∆': 'delta', 1161 '∞': 'begalybe', 1162 '♥': 'meile', 1163 '&': 'ir', 1164 '|': 'ar', 1165 '<': 'maziau nei', 1166 '>': 'daugiau nei', 1167 '∑': 'suma', 1168 '¤': 'valiuta' 1169 }, 1170 1171 'lv': { 1172 '∆': 'delta', 1173 '∞': 'bezgaliba', 1174 '♥': 'milestiba', 1175 '&': 'un', 1176 '|': 'vai', 1177 '<': 'mazak neka', 1178 '>': 'lielaks neka', 1179 '∑': 'summa', 1180 '¤': 'valuta' 1181 }, 1182 1183 'my': { 1184 '∆': 'kwahkhyaet', 1185 '∞': 'asaonasme', 1186 '♥': 'akhyait', 1187 '&': 'nhin', 1188 '|': 'tho', 1189 '<': 'ngethaw', 1190 '>': 'kyithaw', 1191 '∑': 'paungld', 1192 '¤': 'ngwekye' 1193 }, 1194 1195 'mk': {}, 1196 1197 'nl': { 1198 '∆': 'delta', 1199 '∞': 'oneindig', 1200 '♥': 'liefde', 1201 '&': 'en', 1202 '|': 'of', 1203 '<': 'kleiner dan', 1204 '>': 'groter dan', 1205 '∑': 'som', 1206 '¤': 'valuta' 1207 }, 1208 1209 'pl': { 1210 '∆': 'delta', 1211 '∞': 'nieskonczonosc', 1212 '♥': 'milosc', 1213 '&': 'i', 1214 '|': 'lub', 1215 '<': 'mniejsze niz', 1216 '>': 'wieksze niz', 1217 '∑': 'suma', 1218 '¤': 'waluta' 1219 }, 1220 1221 'pt': { 1222 '∆': 'delta', 1223 '∞': 'infinito', 1224 '♥': 'amor', 1225 '&': 'e', 1226 '|': 'ou', 1227 '<': 'menor que', 1228 '>': 'maior que', 1229 '∑': 'soma', 1230 '¤': 'moeda' 1231 }, 1232 1233 'ro': { 1234 '∆': 'delta', 1235 '∞': 'infinit', 1236 '♥': 'dragoste', 1237 '&': 'si', 1238 '|': 'sau', 1239 '<': 'mai mic ca', 1240 '>': 'mai mare ca', 1241 '∑': 'suma', 1242 '¤': 'valuta' 1243 }, 1244 1245 'ru': { 1246 '∆': 'delta', 1247 '∞': 'beskonechno', 1248 '♥': 'lubov', 1249 '&': 'i', 1250 '|': 'ili', 1251 '<': 'menshe', 1252 '>': 'bolshe', 1253 '∑': 'summa', 1254 '¤': 'valjuta' 1255 }, 1256 1257 'sk': { 1258 '∆': 'delta', 1259 '∞': 'nekonecno', 1260 '♥': 'laska', 1261 '&': 'a', 1262 '|': 'alebo', 1263 '<': 'menej ako', 1264 '>': 'viac ako', 1265 '∑': 'sucet', 1266 '¤': 'mena' 1267 }, 1268 1269 'sr': {}, 1270 1271 'tr': { 1272 '∆': 'delta', 1273 '∞': 'sonsuzluk', 1274 '♥': 'ask', 1275 '&': 've', 1276 '|': 'veya', 1277 '<': 'kucuktur', 1278 '>': 'buyuktur', 1279 '∑': 'toplam', 1280 '¤': 'para birimi' 1281 }, 1282 1283 'uk': { 1284 '∆': 'delta', 1285 '∞': 'bezkinechnist', 1286 '♥': 'lubov', 1287 '&': 'i', 1288 '|': 'abo', 1289 '<': 'menshe', 1290 '>': 'bilshe', 1291 '∑': 'suma', 1292 '¤': 'valjuta' 1293 }, 1294 1295 'vn': { 1296 '∆': 'delta', 1297 '∞': 'vo cuc', 1298 '♥': 'yeu', 1299 '&': 'va', 1300 '|': 'hoac', 1301 '<': 'nho hon', 1302 '>': 'lon hon', 1303 '∑': 'tong', 1304 '¤': 'tien te' 1305 } 1306 }; 1307 1308 var uricChars = [';', '?', ':', '@', '&', '=', '+', '$', ',', '/'].join(''); 1309 1310 var uricNoSlashChars = [';', '?', ':', '@', '&', '=', '+', '$', ','].join(''); 1311 1312 var markChars = ['.', '!', '~', '*', "'", '(', ')'].join(''); 1313 1314 /** 1315 * getSlug 1316 * @param {string} input input string 1317 * @param {object|string} opts config object or separator string/char 1318 * @api public 1319 * @return {string} sluggified string 1320 */ 1321 var getSlug = function getSlug(input, opts) { 1322 var separator = '-'; 1323 var result = ''; 1324 var diatricString = ''; 1325 var convertSymbols = true; 1326 var customReplacements = {}; 1327 var maintainCase; 1328 var titleCase; 1329 var truncate; 1330 var uricFlag; 1331 var uricNoSlashFlag; 1332 var markFlag; 1333 var symbol; 1334 var langChar; 1335 var lucky; 1336 var i; 1337 var ch; 1338 var l; 1339 var lastCharWasSymbol; 1340 var lastCharWasDiatric; 1341 var allowedChars = ''; 1342 1343 if (typeof input !== 'string') { 1344 return ''; 1345 } 1346 1347 if (typeof opts === 'string') { 1348 separator = opts; 1349 } 1350 1351 symbol = symbolMap.en; 1352 langChar = langCharMap.en; 1353 1354 if (typeof opts === 'object') { 1355 maintainCase = opts.maintainCase || false; 1356 customReplacements = (opts.custom && typeof opts.custom === 'object') ? opts.custom : customReplacements; 1357 truncate = (+opts.truncate > 1 && opts.truncate) || false; 1358 uricFlag = opts.uric || false; 1359 uricNoSlashFlag = opts.uricNoSlash || false; 1360 markFlag = opts.mark || false; 1361 convertSymbols = (opts.symbols === false || opts.lang === false) ? false : true; 1362 separator = opts.separator || separator; 1363 1364 if (uricFlag) { 1365 allowedChars += uricChars; 1366 } 1367 1368 if (uricNoSlashFlag) { 1369 allowedChars += uricNoSlashChars; 1370 } 1371 1372 if (markFlag) { 1373 allowedChars += markChars; 1374 } 1375 1376 symbol = (opts.lang && symbolMap[opts.lang] && convertSymbols) ? 1377 symbolMap[opts.lang] : (convertSymbols ? symbolMap.en : {}); 1378 1379 langChar = (opts.lang && langCharMap[opts.lang]) ? 1380 langCharMap[opts.lang] : 1381 opts.lang === false || opts.lang === true ? {} : langCharMap.en; 1382 1383 // if titleCase config is an Array, rewrite to object format 1384 if (opts.titleCase && typeof opts.titleCase.length === 'number' && Array.prototype.toString.call(opts.titleCase)) { 1385 opts.titleCase.forEach(function (v) { 1386 customReplacements[v + ''] = v + ''; 1387 }); 1388 1389 titleCase = true; 1390 } else { 1391 titleCase = !!opts.titleCase; 1392 } 1393 1394 // if custom config is an Array, rewrite to object format 1395 if (opts.custom && typeof opts.custom.length === 'number' && Array.prototype.toString.call(opts.custom)) { 1396 opts.custom.forEach(function (v) { 1397 customReplacements[v + ''] = v + ''; 1398 }); 1399 } 1400 1401 // custom replacements 1402 Object.keys(customReplacements).forEach(function (v) { 1403 var r; 1404 1405 if (v.length > 1) { 1406 r = new RegExp('\\b' + escapeChars(v) + '\\b', 'gi'); 1407 } else { 1408 r = new RegExp(escapeChars(v), 'gi'); 1409 } 1410 1411 input = input.replace(r, customReplacements[v]); 1412 }); 1413 1414 // add all custom replacement to allowed charlist 1415 for (ch in customReplacements) { 1416 allowedChars += ch; 1417 } 1418 } 1419 1420 allowedChars += separator; 1421 1422 // escape all necessary chars 1423 allowedChars = escapeChars(allowedChars); 1424 1425 // trim whitespaces 1426 input = input.replace(/(^\s+|\s+$)/g, ''); 1427 1428 lastCharWasSymbol = false; 1429 lastCharWasDiatric = false; 1430 1431 for (i = 0, l = input.length; i < l; i++) { 1432 ch = input[i]; 1433 1434 if (isReplacedCustomChar(ch, customReplacements)) { 1435 // don't convert a already converted char 1436 lastCharWasSymbol = false; 1437 } else if (langChar[ch]) { 1438 // process language specific diactrics chars conversion 1439 ch = lastCharWasSymbol && langChar[ch].match(/[A-Za-z0-9]/) ? ' ' + langChar[ch] : langChar[ch]; 1440 1441 lastCharWasSymbol = false; 1442 } else if (ch in charMap) { 1443 // the transliteration changes entirely when some special characters are added 1444 if (i + 1 < l && lookAheadCharArray.indexOf(input[i + 1]) >= 0) { 1445 diatricString += ch; 1446 ch = ''; 1447 } else if (lastCharWasDiatric === true) { 1448 ch = diatricMap[diatricString] + charMap[ch]; 1449 diatricString = ''; 1450 } else { 1451 // process diactrics chars 1452 ch = lastCharWasSymbol && charMap[ch].match(/[A-Za-z0-9]/) ? ' ' + charMap[ch] : charMap[ch]; 1453 } 1454 1455 lastCharWasSymbol = false; 1456 lastCharWasDiatric = false; 1457 } else if (ch in diatricMap) { 1458 diatricString += ch; 1459 ch = ''; 1460 // end of string, put the whole meaningful word 1461 if (i === l - 1) { 1462 ch = diatricMap[diatricString]; 1463 } 1464 lastCharWasDiatric = true; 1465 } else if ( 1466 // process symbol chars 1467 symbol[ch] && !(uricFlag && uricChars 1468 .indexOf(ch) !== -1) && !(uricNoSlashFlag && uricNoSlashChars 1469 // .indexOf(ch) !== -1) && !(markFlag && markChars 1470 .indexOf(ch) !== -1)) { 1471 ch = lastCharWasSymbol || result.substr(-1).match(/[A-Za-z0-9]/) ? separator + symbol[ch] : symbol[ch]; 1472 ch += input[i + 1] !== void 0 && input[i + 1].match(/[A-Za-z0-9]/) ? separator : ''; 1473 1474 lastCharWasSymbol = true; 1475 } else { 1476 if (lastCharWasDiatric === true) { 1477 ch = diatricMap[diatricString] + ch; 1478 diatricString = ''; 1479 lastCharWasDiatric = false; 1480 } else if (lastCharWasSymbol && (/[A-Za-z0-9]/.test(ch) || result.substr(-1).match(/A-Za-z0-9]/))) { 1481 // process latin chars 1482 ch = ' ' + ch; 1483 } 1484 lastCharWasSymbol = false; 1485 } 1486 1487 // add allowed chars 1488 result += ch.replace(new RegExp('[^\\w\\s' + allowedChars + '_-]', 'g'), separator); 1489 } 1490 1491 if (titleCase) { 1492 result = result.replace(/(\w)(\S*)/g, function (_, i, r) { 1493 var j = i.toUpperCase() + (r !== null ? r : ''); 1494 return (Object.keys(customReplacements).indexOf(j.toLowerCase()) < 0) ? j : j.toLowerCase(); 1495 }); 1496 } 1497 1498 // eliminate duplicate separators 1499 // add separator 1500 // trim separators from start and end 1501 result = result.replace(/\s+/g, separator) 1502 .replace(new RegExp('\\' + separator + '+', 'g'), separator) 1503 .replace(new RegExp('(^\\' + separator + '+|\\' + separator + '+$)', 'g'), ''); 1504 1505 if (truncate && result.length > truncate) { 1506 lucky = result.charAt(truncate) === separator; 1507 result = result.slice(0, truncate); 1508 1509 if (!lucky) { 1510 result = result.slice(0, result.lastIndexOf(separator)); 1511 } 1512 } 1513 1514 if (!maintainCase && !titleCase) { 1515 result = result.toLowerCase(); 1516 } 1517 1518 return result; 1519 }; 1520 1521 /** 1522 * createSlug curried(opts)(input) 1523 * @param {object|string} opts config object or input string 1524 * @return {Function} function getSlugWithConfig() 1525 **/ 1526 var createSlug = function createSlug(opts) { 1527 1528 /** 1529 * getSlugWithConfig 1530 * @param {string} input string 1531 * @return {string} slug string 1532 */ 1533 return function getSlugWithConfig(input) { 1534 return getSlug(input, opts); 1535 }; 1536 }; 1537 1538 /** 1539 * escape Chars 1540 * @param {string} input string 1541 */ 1542 var escapeChars = function escapeChars(input) { 1543 return input.replace(/[-\\^$*+?.()|[\]{}\/]/g, '\\$&'); 1544 }; 1545 1546 /** 1547 * check if the char is an already converted char from custom list 1548 * @param {char} ch character to check 1549 * @param {object} customReplacements custom translation map 1550 */ 1551 var isReplacedCustomChar = function (ch, customReplacements) { 1552 for (var c in customReplacements) { 1553 if (customReplacements[c] === ch) { 1554 return true; 1555 } 1556 } 1557 }; 1558 1559 if (typeof module !== 'undefined' && module.exports) { 1560 1561 // export functions for use in Node 1562 module.exports = getSlug; 1563 module.exports.createSlug = createSlug; 1564 } else if (typeof define !== 'undefined' && define.amd) { 1565 1566 // export function for use in AMD 1567 define([], function () { 1568 return getSlug; 1569 }); 1570 } else { 1571 1572 // don't overwrite global if exists 1573 try { 1574 if (root.getSlug || root.createSlug) { 1575 throw 'speakingurl: globals exists /(getSlug|createSlug)/'; 1576 } else { 1577 root.getSlug = getSlug; 1578 root.createSlug = createSlug; 1579 } 1580 } catch (e) {} 1581 } 1582 })(this);