lib/util: add several utils from jptools

This commit is contained in:
2025-04-29 12:14:40 +02:00
parent 929be590ee
commit 38706c0532
9 changed files with 393 additions and 4 deletions

View File

@@ -0,0 +1,303 @@
import 'dart:core';
// Run in console on http://www.kumamotokokufu-h.ed.jp/kumamoto/bungaku/nengoui.html
// Array.from(document.querySelectorAll('table')[1].querySelectorAll('tr')).slice(1).map(row => `DateTime(${row.children[3 + (row.children.length == 7)].innerHTML.replace(/.*/, '')}, ${row.children[4 + (row.children.length == 7)].innerHTML.replace('/', ', ')}): '${row.children[2 + (row.children.length == 7)].innerHTML}'`).join('\n')
const Map<(int, int, int), String> periodsBeforeNanbokuchou = {
(645, 6, 19): '大化',
(650, 2, 15): '白雉',
(686, 7, 20): '朱鳥',
(701, 3, 21): '大宝',
(704, 5, 10): '慶雲',
(708, 1, 11): '和銅',
(715, 9, 2): '霊亀',
(717, 11, 17): '養老',
(724, 2, 4): '神亀',
(729, 8, 5): '天平',
(749, 4, 14): '天平感宝',
(749, 7, 2): '天平勝宝',
(757, 8, 18): '天平宝字',
(765, 1, 7): '天平神護',
(767, 8, 16): '神護景雲',
(770, 10, 1): '宝亀',
(781, 1, 1): '天応',
(782, 8, 19): '延暦',
(806, 5, 18): '大同',
(810, 9, 19): '弘仁',
(824, 1, 5): '天長',
(834, 1, 3): '承和',
(848, 6, 13): '嘉祥',
(851, 4, 28): '仁寿',
(854, 11, 30): '斎衡',
(857, 2, 21): '天安',
(859, 4, 15): '貞観',
(877, 4, 16): '元慶',
(885, 2, 21): '仁和',
(889, 4, 27): '寛平',
(898, 4, 26): '昌泰',
(901, 7, 15): '延喜',
(923, 4, 11): '延長',
(931, 4, 26): '承平',
(938, 5, 22): '天慶',
(947, 4, 22): '天暦',
(957, 10, 27): '天徳',
(961, 2, 16): '応和',
(964, 7, 10): '康保',
(968, 8, 13): '安和',
(970, 3, 25): '天禄',
(973, 12, 20): '天延',
(976, 7, 13): '貞元',
(978, 11, 29): '天元',
(983, 4, 15): '永観',
(985, 4, 27): '寛和',
(987, 4, 5): '永延',
(989, 8, 8): '永祚',
(990, 11, 7): '正暦',
(995, 2, 22): '長徳',
(999, 1, 13): '長保',
(1004, 7, 20): '寛弘',
(1012, 12, 25): '長和',
(1017, 4, 23): '寛仁',
(1021, 2, 2): '治安',
(1024, 7, 13): '万寿',
(1028, 7, 25): '長元',
(1037, 4, 21): '長暦',
(1040, 11, 10): '長久',
(1044, 11, 24): '寛徳',
(1046, 4, 14): '永承',
(1053, 1, 11): '天喜',
(1058, 8, 29): '康平',
(1065, 8, 2): '治暦',
(1069, 4, 13): '延久',
(1074, 8, 23): '承保',
(1077, 11, 17): '承暦',
(1081, 2, 10): '永保',
(1084, 2, 7): '応徳',
(1087, 4, 7): '寛治',
(1094, 12, 15): '嘉保',
(1096, 12, 17): '永長',
(1097, 11, 21): '承徳',
(1099, 8, 28): '康和',
(1104, 2, 10): '長治',
(1106, 4, 9): '嘉承',
(1108, 8, 3): '天仁',
(1110, 7, 13): '天永',
(1113, 7, 13): '永久',
(1118, 4, 3): '元永',
(1120, 4, 10): '保安',
(1124, 4, 3): '天治',
(1126, 1, 22): '大治',
(1131, 1, 29): '天承',
(1132, 8, 11): '長承',
(1135, 4, 27): '保延',
(1141, 7, 10): '永治',
(1142, 4, 28): '康治',
(1144, 2, 23): '天養',
(1145, 7, 22): '久安',
(1151, 1, 26): '仁平',
(1154, 10, 28): '久寿',
(1156, 4, 27): '保元',
(1159, 4, 20): '平治',
(1160, 1, 10): '永暦',
(1161, 9, 4): '応保',
(1163, 3, 29): '長寛',
(1165, 6, 5): '永万',
(1166, 8, 27): '仁安',
(1169, 4, 8): '嘉応',
(1171, 4, 21): '承安',
(1175, 7, 28): '安元',
(1177, 8, 4): '治承',
(1181, 7, 14): '養和',
(1182, 5, 27): '寿永',
(1184, 4, 16): '元暦',
(1185, 8, 14): '文治',
(1190, 4, 11): '建久',
(1199, 4, 27): '正治',
(1201, 2, 13): '建仁',
(1204, 2, 20): '元久',
(1206, 4, 27): '建永',
(1207, 10, 25): '承元',
(1211, 3, 9): '建暦',
(1213, 12, 6): '建保',
(1219, 4, 12): '承久',
(1222, 4, 13): '貞応',
(1224, 11, 20): '元仁',
(1225, 4, 20): '嘉禄',
(1227, 12, 10): '安貞',
(1229, 3, 5): '寛喜',
(1232, 4, 2): '貞永',
(1233, 4, 15): '天福',
(1234, 11, 5): '文暦',
(1235, 9, 19): '嘉禎',
(1238, 11, 23): '暦仁',
(1239, 2, 7): '延応',
(1240, 7, 16): '仁治',
(1243, 2, 26): '寛元',
(1247, 2, 28): '宝治',
(1249, 3, 18): '建長',
(1256, 10, 5): '康元',
(1257, 3, 14): '正嘉',
(1259, 3, 26): '正元',
(1260, 4, 13): '文応',
(1261, 2, 20): '弘長',
(1264, 2, 28): '文永',
(1275, 4, 25): '建治',
(1278, 2, 29): '弘安',
(1288, 4, 28): '正応',
(1293, 8, 5): '永仁',
(1299, 4, 25): '正安',
(1302, 11, 21): '乾元',
(1303, 8, 5): '嘉元',
(1306, 12, 14): '徳治',
(1308, 10, 9): '延慶',
(1311, 4, 28): '応長',
(1312, 3, 20): '正和',
(1317, 2, 3): '文保',
(1319, 4, 28): '元応',
(1321, 2, 23): '元亨',
(1324, 12, 9): '正中',
(1326, 4, 26): '嘉暦',
};
const Map<(int, int, int), String> periodsNanbokuchouNorth = {
(1329, 8, 29): '元徳',
(1332, 4, 28): '正慶',
(1334, 1, 29): '建武',
(1338, 8, 28): '暦応',
(1342, 4, 27): '康永',
(1345, 10, 21): '貞和',
(1350, 2, 27): '観応',
(1352, 9, 27): '文和',
(1356, 3, 28): '延文',
(1361, 3, 29): '康安',
(1362, 9, 23): '貞治',
(1368, 2, 18): '応安',
(1375, 2, 27): '永和',
(1379, 3, 22): '康暦',
(1381, 2, 24): '永徳',
(1384, 2, 27): '至徳',
(1387, 8, 23): '嘉慶',
(1389, 2, 9): '康応',
(1390, 3, 26): '明徳',
};
const Map<(int, int, int), String> periodsNanbokuchouSouth = {
(1329, 8, 29): '元徳',
(1331, 8, 9): '元弘',
(1334, 1, 29): '建武',
(1336, 2, 29): '延元',
(1340, 4, 28): '興国',
(1346, 12, 8): '正平',
(1370, 7, 24): '建徳',
(1372, 4, 4): '文中',
(1375, 5, 27): '天授',
(1381, 2, 10): '弘和',
(1384, 4, 28): '元中',
};
const Map<(int, int, int), String> periodsAfterNanbokuchou = {
// (1392, ): '室町時代',
(1394, 7, 5): '応永',
(1428, 4, 27): '正長',
(1429, 9, 5): '永享',
(1441, 2, 17): '嘉吉',
(1444, 2, 5): '文安',
(1449, 7, 28): '宝徳',
(1452, 7, 25): '享徳',
(1455, 7, 25): '康正',
(1457, 9, 28): '長禄',
(1460, 12, 21): '寛正',
(1466, 2, 28): '文正',
(1467, 3, 5): '応仁',
(1469, 4, 28): '文明',
(1487, 7, 20): '長享',
(1489, 8, 21): '延徳',
(1492, 7, 19): '明応',
(1501, 2, 29): '文亀',
(1504, 2, 30): '永正',
(1521, 8, 23): '大永',
(1528, 8, 20): '享禄',
(1532, 7, 29): '天文',
(1555, 10, 23): '弘治',
(1558, 2, 28): '永禄',
(1570, 4, 23): '元亀',
(1573, 7, 28): '天正',
(1592, 12, 8): '文禄',
(1596, 10, 27): '慶長',
(1615, 7, 13): '元和',
(1624, 2, 30): '寛永',
(1644, 12, 16): '正保',
(1648, 2, 15): '慶安',
(1652, 9, 18): '承応',
(1655, 4, 13): '明暦',
(1658, 7, 23): '万治',
(1661, 4, 25): '寛文',
(1673, 9, 21): '延宝',
(1681, 9, 29): '天和',
(1684, 2, 21): '貞享',
(1688, 9, 30): '元禄',
(1704, 3, 13): '宝永',
(1711, 4, 25): '正徳',
(1716, 6, 22): '享保',
(1736, 4, 28): '元文',
(1741, 2, 27): '寛保',
(1744, 2, 21): '延享',
(1748, 7, 12): '寛延',
(1751, 10, 27): '宝暦',
(1764, 6, 2): '明和',
(1772, 11, 16): '安永',
(1781, 4, 2): '天明',
(1789, 1, 25): '寛政',
(1801, 2, 5): '享和',
(1804, 2, 11): '文化',
(1818, 4, 22): '文政',
(1830, 12, 10): '天保',
(1844, 12, 2): '弘化',
(1848, 2, 28): '嘉永',
(1854, 11, 27): '安政',
(1860, 3, 18): '万延',
(1861, 2, 19): '文久',
(1864, 2, 20): '元治',
(1865, 4, 7): '慶応',
(1868, 9, 8): '明治',
(1912, 7, 30): '大正',
(1926, 12, 25): '昭和',
(1989, 1, 8): '平成',
(2019, 5, 1): '令和',
};
extension on DateTime {
/// Note: In the years between 1336 and 1392, Japan was split in two
/// because of an ongoing conflict. As a result, Japan has two timelines
/// during these years. Unless you turn off [nanbokuchouPeriodUsesNorth],
/// function will give you the timeline from the northern part of Japan
/// as a default.
///
/// See more info here:
/// - https://en.wikipedia.org/wiki/Nanboku-ch%C5%8D_period
/// - http://www.kumamotokokufu-h.ed.jp/kumamoto/bungaku/nengoui.html
String? japaneseEra({bool nanbokuchouPeriodUsesNorth = true}) {
throw UnimplementedError('This function is not implemented yet.');
if (this.year < 645) {
return null;
}
if (this.year < periodsNanbokuchouNorth.keys.first.$1) {
// TODO: find first where year <= this.year and jump one period back.
}
}
String get japaneseWeekdayPrefix => [
'',
'',
'',
'',
'',
'',
'',
][weekday - 1];
/// Returns the date in Japanese format.
String japaneseDate({bool showWeekday = false}) => '$month月$day日' + (showWeekday ? '$japaneseWeekdayPrefix' : '');
}

2152
lib/util/jouyou_kanji.dart Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,58 @@
const Map<int, String> numberToKanjiMap = {
0: '',
1: '',
2: '',
3: '',
4: '',
5: '',
6: '',
7: '',
8: '',
9: '',
10: '',
100: '',
1000: '',
10000: '',
100000000: '',
1000000000000: '',
};
const Map<int, String> extendedNumberToKanjiMap = {
16: '',
20: '',
24: '𥝱',
28: '',
32: '',
36: '',
40: '',
44: '',
48: '',
};
const Map<int, String> numberToFormalKanjiMap = {
0: '',
1: '',
2: '',
3: '',
4: '',
5: '',
6: '',
7: '',
8: '',
9: '',
10: '',
100: '',
1000: '',
10000: '',
};
const String yenSymbol = '';
const String formalYenSymbol = '';
String numberToKanji(int number, {bool formal = false}) {
throw UnimplementedError();
}
int kanjiToNumber(String kanji) {
throw UnimplementedError();
}

View File

@@ -0,0 +1,622 @@
// Source: https://github.com/Kimtaro/ve/blob/master/lib/providers/japanese_transliterators.rb
const hiragana_syllabic_n = '';
const hiragana_small_tsu = '';
const Map<String, String> hiragana_to_latin = {
'': 'a',
'': 'i',
'': 'u',
'': 'e',
'': 'o',
'': 'ka',
'': 'ki',
'': 'ku',
'': 'ke',
'': 'ko',
'': 'ga',
'': 'gi',
'': 'gu',
'': 'ge',
'': 'go',
'': 'sa',
'': 'shi',
'': 'su',
'': 'se',
'': 'so',
'': 'za',
'': 'ji',
'': 'zu',
'': 'ze',
'': 'zo',
'': 'ta',
'': 'chi',
'': 'tsu',
'': 'te',
'': 'to',
'': 'da',
'': 'ji',
'': 'zu',
'': 'de',
'': 'do',
'': 'na',
'': 'ni',
'': 'nu',
'': 'ne',
'': 'no',
'': 'ha',
'': 'hi',
'': 'fu',
'': 'he',
'': 'ho',
'': 'ba',
'': 'bi',
'': 'bu',
'': 'be',
'': 'bo',
'': 'pa',
'': 'pi',
'': 'pu',
'': 'pe',
'': 'po',
'': 'ma',
'': 'mi',
'': 'mu',
'': 'me',
'': 'mo',
'': 'ya',
'': 'yu',
'': 'yo',
'': 'ra',
'': 'ri',
'': 'ru',
'': 're',
'': 'ro',
'': 'wa',
'うぃ': 'whi',
'うぇ': 'whe',
'': 'wo',
'': 'we',
'': 'wi',
'': '-',
'': 'n',
'きゃ': 'kya',
'きゅ': 'kyu',
'きょ': 'kyo',
'きぇ': 'kye',
'きぃ': 'kyi',
'ぎゃ': 'gya',
'ぎゅ': 'gyu',
'ぎょ': 'gyo',
'ぎぇ': 'gye',
'ぎぃ': 'gyi',
'くぁ': 'kwa',
'くぃ': 'kwi',
'くぅ': 'kwu',
'くぇ': 'kwe',
'くぉ': 'kwo',
'ぐぁ': 'qwa',
'ぐぃ': 'gwi',
'ぐぅ': 'gwu',
'ぐぇ': 'gwe',
'ぐぉ': 'gwo',
'しゃ': 'sha',
'しぃ': 'syi',
'しゅ': 'shu',
'しぇ': 'she',
'しょ': 'sho',
'じゃ': 'ja',
'じゅ': 'ju',
'じぇ': 'jye',
'じょ': 'jo',
'じぃ': 'jyi',
'すぁ': 'swa',
'すぃ': 'swi',
'すぅ': 'swu',
'すぇ': 'swe',
'すぉ': 'swo',
'ちゃ': 'cha',
'ちゅ': 'chu',
'ちぇ': 'tye',
'ちょ': 'cho',
'ちぃ': 'tyi',
'ぢゃ': 'ja',
'ぢぃ': 'dyi',
'ぢゅ': 'ju',
'ぢぇ': 'dye',
'ぢょ': 'jo',
'つぁ': 'tsa',
'つぃ': 'tsi',
'つぇ': 'tse',
'つぉ': 'tso',
'てゃ': 'tha',
'てぃ': 'thi',
'てゅ': 'thu',
'てぇ': 'the',
'てょ': 'tho',
'とぁ': 'twa',
'とぃ': 'twi',
'とぅ': 'twu',
'とぇ': 'twe',
'とぉ': 'two',
'でゃ': 'dha',
'でぃ': 'dhi',
'でゅ': 'dhu',
'でぇ': 'dhe',
'でょ': 'dho',
'どぁ': 'dwa',
'どぃ': 'dwi',
'どぅ': 'dwu',
'どぇ': 'dwe',
'どぉ': 'dwo',
'にゃ': 'nya',
'にゅ': 'nyu',
'にょ': 'nyo',
'にぇ': 'nye',
'にぃ': 'nyi',
'ひゃ': 'hya',
'ひぃ': 'hyi',
'ひゅ': 'hyu',
'ひぇ': 'hye',
'ひょ': 'hyo',
'びゃ': 'bya',
'びぃ': 'byi',
'びゅ': 'byu',
'びぇ': 'bye',
'びょ': 'byo',
'ぴゃ': 'pya',
'ぴぃ': 'pyi',
'ぴゅ': 'pyu',
'ぴぇ': 'pye',
'ぴょ': 'pyo',
'ふぁ': 'fwa',
'ふぃ': 'fyi',
'ふぇ': 'fye',
'ふぉ': 'fwo',
'ふぅ': 'fwu',
'ふゃ': 'fya',
'ふゅ': 'fyu',
'ふょ': 'fyo',
'みゃ': 'mya',
'みぃ': 'myi',
'みゅ': 'myu',
'みぇ': 'mye',
'みょ': 'myo',
'りゃ': 'rya',
'りぃ': 'ryi',
'りゅ': 'ryu',
'りぇ': 'rye',
'りょ': 'ryo',
'ゔぁ': 'va',
'ゔぃ': 'vyi',
'': 'vu',
'ゔぇ': 'vye',
'ゔぉ': 'vo',
'ゔゃ': 'vya',
'ゔゅ': 'vyu',
'ゔょ': 'vyo',
'うぁ': 'wha',
'いぇ': 'ye',
'うぉ': 'who',
'': 'xa',
'': 'xi',
'': 'xu',
'': 'xe',
'': 'xo',
'': 'xka',
'': 'xke',
'': 'xwa'
};
const Map<String, String> latin_to_hiragana = {
'a': '',
'i': '',
'u': '',
'e': '',
'o': '',
'ka': '',
'ki': '',
'ku': '',
'ke': '',
'ko': '',
'ga': '',
'gi': '',
'gu': '',
'ge': '',
'go': '',
'sa': '',
'si': '',
'shi': '',
'su': '',
'se': '',
'so': '',
'za': '',
'zi': '',
'ji': '',
'zu': '',
'ze': '',
'zo': '',
'ta': '',
'ti': '',
'chi': '',
'tu': '',
'tsu': '',
'te': '',
'to': '',
'da': '',
'di': '',
'du': '',
'dzu': '',
'de': '',
'do': '',
'na': '',
'ni': '',
'nu': '',
'ne': '',
'no': '',
'ha': '',
'hi': '',
'hu': '',
'fu': '',
'he': '',
'ho': '',
'ba': '',
'bi': '',
'bu': '',
'be': '',
'bo': '',
'pa': '',
'pi': '',
'pu': '',
'pe': '',
'po': '',
'ma': '',
'mi': '',
'mu': '',
'me': '',
'mo': '',
'ya': '',
'yu': '',
'yo': '',
'ra': '',
'ri': '',
'ru': '',
're': '',
'ro': '',
'la': '',
'li': '',
'lu': '',
'le': '',
'lo': '',
'wa': '',
'wi': 'うぃ',
'we': 'うぇ',
'wo': '',
'wye': '',
'wyi': '',
'-': '',
'n': '',
'nn': '',
"n'": '',
'kya': 'きゃ',
'kyu': 'きゅ',
'kyo': 'きょ',
'kye': 'きぇ',
'kyi': 'きぃ',
'gya': 'ぎゃ',
'gyu': 'ぎゅ',
'gyo': 'ぎょ',
'gye': 'ぎぇ',
'gyi': 'ぎぃ',
'kwa': 'くぁ',
'kwi': 'くぃ',
'kwu': 'くぅ',
'kwe': 'くぇ',
'kwo': 'くぉ',
'gwa': 'ぐぁ',
'gwi': 'ぐぃ',
'gwu': 'ぐぅ',
'gwe': 'ぐぇ',
'gwo': 'ぐぉ',
'qwa': 'ぐぁ',
'qwi': 'ぐぃ',
'qwu': 'ぐぅ',
'qwe': 'ぐぇ',
'qwo': 'ぐぉ',
'sya': 'しゃ',
'syi': 'しぃ',
'syu': 'しゅ',
'sye': 'しぇ',
'syo': 'しょ',
'sha': 'しゃ',
'shu': 'しゅ',
'she': 'しぇ',
'sho': 'しょ',
'ja': 'じゃ',
'ju': 'じゅ',
'je': 'じぇ',
'jo': 'じょ',
'jya': 'じゃ',
'jyi': 'じぃ',
'jyu': 'じゅ',
'jye': 'じぇ',
'jyo': 'じょ',
'zya': 'じゃ',
'zyu': 'じゅ',
'zyo': 'じょ',
'zye': 'じぇ',
'zyi': 'じぃ',
'swa': 'すぁ',
'swi': 'すぃ',
'swu': 'すぅ',
'swe': 'すぇ',
'swo': 'すぉ',
'cha': 'ちゃ',
'chu': 'ちゅ',
'che': 'ちぇ',
'cho': 'ちょ',
'cya': 'ちゃ',
'cyi': 'ちぃ',
'cyu': 'ちゅ',
'cye': 'ちぇ',
'cyo': 'ちょ',
'tya': 'ちゃ',
'tyi': 'ちぃ',
'tyu': 'ちゅ',
'tye': 'ちぇ',
'tyo': 'ちょ',
'dya': 'ぢゃ',
'dyi': 'ぢぃ',
'dyu': 'ぢゅ',
'dye': 'ぢぇ',
'dyo': 'ぢょ',
'tsa': 'つぁ',
'tsi': 'つぃ',
'tse': 'つぇ',
'tso': 'つぉ',
'tha': 'てゃ',
'thi': 'てぃ',
'thu': 'てゅ',
'the': 'てぇ',
'tho': 'てょ',
'twa': 'とぁ',
'twi': 'とぃ',
'twu': 'とぅ',
'twe': 'とぇ',
'two': 'とぉ',
'dha': 'でゃ',
'dhi': 'でぃ',
'dhu': 'でゅ',
'dhe': 'でぇ',
'dho': 'でょ',
'dwa': 'どぁ',
'dwi': 'どぃ',
'dwu': 'どぅ',
'dwe': 'どぇ',
'dwo': 'どぉ',
'nya': 'にゃ',
'nyu': 'にゅ',
'nyo': 'にょ',
'nye': 'にぇ',
'nyi': 'にぃ',
'hya': 'ひゃ',
'hyi': 'ひぃ',
'hyu': 'ひゅ',
'hye': 'ひぇ',
'hyo': 'ひょ',
'bya': 'びゃ',
'byi': 'びぃ',
'byu': 'びゅ',
'bye': 'びぇ',
'byo': 'びょ',
'pya': 'ぴゃ',
'pyi': 'ぴぃ',
'pyu': 'ぴゅ',
'pye': 'ぴぇ',
'pyo': 'ぴょ',
'fa': 'ふぁ',
'fi': 'ふぃ',
'fe': 'ふぇ',
'fo': 'ふぉ',
'fwa': 'ふぁ',
'fwi': 'ふぃ',
'fwu': 'ふぅ',
'fwe': 'ふぇ',
'fwo': 'ふぉ',
'fya': 'ふゃ',
'fyi': 'ふぃ',
'fyu': 'ふゅ',
'fye': 'ふぇ',
'fyo': 'ふょ',
'mya': 'みゃ',
'myi': 'みぃ',
'myu': 'みゅ',
'mye': 'みぇ',
'myo': 'みょ',
'rya': 'りゃ',
'ryi': 'りぃ',
'ryu': 'りゅ',
'rye': 'りぇ',
'ryo': 'りょ',
'lya': 'りゃ',
'lyu': 'りゅ',
'lyo': 'りょ',
'lye': 'りぇ',
'lyi': 'りぃ',
'va': 'ゔぁ',
'vi': 'ゔぃ',
'vu': '',
've': 'ゔぇ',
'vo': 'ゔぉ',
'vya': 'ゔゃ',
'vyi': 'ゔぃ',
'vyu': 'ゔゅ',
'vye': 'ゔぇ',
'vyo': 'ゔょ',
'wha': 'うぁ',
'whi': 'うぃ',
'ye': 'いぇ',
'whe': 'うぇ',
'who': 'うぉ',
'xa': '',
'xi': '',
'xu': '',
'xe': '',
'xo': '',
'xya': '',
'xyu': '',
'xyo': '',
'xtu': '',
'xtsu': '',
'xka': '',
'xke': '',
'xwa': '',
'@@': ' ',
'#[': '',
'#]': '',
'#,': '',
'#.': '',
'#/': '',
};
bool _smallTsu(String for_conversion) => for_conversion == hiragana_small_tsu;
bool _nFollowedByYuYeYo(String for_conversion, String kana) =>
for_conversion == hiragana_syllabic_n &&
kana.length > 1 &&
'やゆよ'.contains(kana.substring(1, 2));
String transliterateHiraganaToLatin(String hiragana) {
String kana = hiragana;
String romaji = '';
bool geminate = false;
while (kana.isNotEmpty) {
final lengths = [if (kana.length > 1) 2, 1];
for (final length in lengths) {
final String for_conversion = kana.substring(0, length);
String? mora;
if (_smallTsu(for_conversion)) {
geminate = true;
kana = kana.replaceRange(0, length, '');
break;
} else if (_nFollowedByYuYeYo(for_conversion, kana)) {
mora = "n'";
}
mora ??= hiragana_to_latin[for_conversion];
if (mora != null) {
if (geminate) {
geminate = false;
romaji += mora.substring(0, 1);
}
romaji += mora;
kana = kana.replaceRange(0, length, '');
break;
} else if (length == 1) {
romaji += for_conversion;
kana = kana.replaceRange(0, length, '');
}
}
}
return romaji;
}
bool _doubleNFollowedByAIUEO(String for_conversion) =>
RegExp(r'^nn[aiueo]$').hasMatch(for_conversion);
bool _hasTableMatch(String for_conversion) =>
latin_to_hiragana[for_conversion] != null;
bool _hasDoubleConsonant(String for_conversion, int length) =>
for_conversion == 'tch' ||
(length == 2 &&
RegExp(r'^([kgsztdnbpmyrlwchf])\1$').hasMatch(for_conversion));
String transliterateLatinToHiragana(String latin) {
String romaji =
latin.toLowerCase().replaceAll('mb', 'nb').replaceAll('mp', 'np');
String kana = '';
while (romaji.isNotEmpty) {
final lengths = [
if (romaji.length > 2) 3,
if (romaji.length > 1) 2,
1,
];
for (final length in lengths) {
String? mora;
int for_removal = length;
final String for_conversion = romaji.substring(0, length);
if (_doubleNFollowedByAIUEO(for_conversion)) {
mora = hiragana_syllabic_n;
for_removal = 1;
} else if (_hasTableMatch(for_conversion)) {
mora = latin_to_hiragana[for_conversion];
} else if (_hasDoubleConsonant(for_conversion, length)) {
mora = hiragana_small_tsu;
for_removal = 1;
}
if (mora != null) {
kana += mora;
romaji = romaji.replaceRange(0, for_removal, '');
break;
} else if (length == 1) {
kana += for_conversion;
romaji = romaji.replaceRange(0, 1, '');
}
}
}
return kana;
}
String _transposeCodepointsInRange(
String text,
int distance,
int rangeStart,
int rangeEnd,
) =>
String.fromCharCodes(
text.codeUnits
.map((c) => c + ((rangeStart <= c && c <= rangeEnd) ? distance : 0)),
);
String transliterateKanaToLatin(String kana) =>
transliterateHiraganaToLatin(transliterateKatakanaToHiragana(kana));
String transliterateLatinToKatakana(String latin) =>
transliterateHiraganaToKatakana(transliterateLatinToHiragana(latin));
String transliterateKatakanaToHiragana(String katakana) =>
_transposeCodepointsInRange(katakana, -96, 12449, 12534);
String transliterateHiraganaToKatakana(String hiragana) =>
_transposeCodepointsInRange(hiragana, 96, 12353, 12438);
String transliterateFullwidthRomajiToHalfwidth(String halfwidth) =>
_transposeCodepointsInRange(
_transposeCodepointsInRange(
halfwidth,
-65248,
65281,
65374,
),
-12256,
12288,
12288,
);
String transliterateHalfwidthRomajiToFullwidth(String halfwidth) =>
_transposeCodepointsInRange(
_transposeCodepointsInRange(
halfwidth,
65248,
33,
126,
),
12256,
32,
32,
);

View File

@@ -0,0 +1,28 @@
/// The string version of a regex that will match any Unified CJK Character.
/// This includes the ranges (), ()
///
/// See https://www.regular-expressions.info/unicode.html
///
/// Remember to turn on the unicode flag when making a new RegExp.
const String rawKanjiRegex = r'\p{Script=Hani}';
/// The string version of a regex that will match any katakana.
/// This includes the ranges (), ()
///
/// See https://www.regular-expressions.info/unicode.html
///
/// Remember to turn on the unicode flag when making a new RegExp.
const String rawKatakanaRegex = r'\p{Script=Katakana}';
/// The string version of a regex that will match any hiragana.
/// This includes the ranges (), ()
///
/// See https://www.regular-expressions.info/unicode.html
///
/// Remember to turn on the unicode flag when making a new RegExp.
const String rawHiraganaRegex = r'\p{Script=Hiragana}';
final RegExp kanjiRegex = RegExp(rawKanjiRegex, unicode: true);
final RegExp katakanaRegex = RegExp(rawKatakanaRegex, unicode: true);
final RegExp hiraganaRegex = RegExp(rawHiraganaRegex, unicode: true);