Files
makemeahanzi/lib/pinyin_util.js
2016-07-31 01:20:33 -04:00

81 lines
2.6 KiB
JavaScript

import {assert} from '/lib/base';
const vowel_to_tone =
{0: "aeiouü", 1: "āēīōūǖ", 2: "áéíóúǘ", 3: "ǎěǐǒǔǚ", 4: "àèìòùǜ"};
const tokenSet = (tokens) => {
const result = {};
tokens.split(' ').map((x) => result[x] = true);
return result;
}
const consonants = tokenSet('b p m f d t n l g k h j q x zh ch sh r z c s y w');
const vowels = tokenSet('a ai an ang ao e ei en eng er i ia ian iang iao ie ' +
'in ing io iong iu o ong ou u ua uai uan uang ue ui ' +
'un uo v van vn');
const two_syllables = tokenSet('ia ian iang iao ie io iong iu ua uai uan ' +
'uang ue ui uo van');
const pinyin_util = {};
pinyin_util.dropTones = (pinyin, append_number) => {
for (let i = 0; i < pinyin.length; i++) {
for (let option = 1; option <= 4; option++) {
const index = vowel_to_tone[option].indexOf(pinyin[i]);
if (index >= 0) {
const toneless = 'aeiouv'[index];
pinyin = pinyin.substr(0, i) + toneless + pinyin.substr(i + 1);
if (append_number) {
return `${pinyin}${option}`;
}
}
}
}
return pinyin;
}
pinyin_util.numberedPinyinToTonePinyin = (numbered) => {
assert(numbered && numbered === numbered.toLowerCase());
let tone = 0;
if ('01234'.indexOf(numbered[numbered.length - 1]) >= 0) {
tone = parseInt(numbered[numbered.length - 1], 10);
numbered = numbered.substr(0, numbered.length - 1);
}
for (let i = 0; i < numbered.length; i++) {
for (let option = 1; option <= 4; option++) {
const index = vowel_to_tone[option].indexOf(numbered[i]);
if (index >= 0) {
tone = option;
const toneless = 'aeiouv'[index];
numbered = numbered.substr(0, i) + toneless + numbered.substr(i + 1);
}
}
}
let consonant = '';
for (let i = 1; i < numbered.length; i++) {
const candidate = numbered.substr(0, i);
if (consonants[candidate]) {
consonant = candidate;
} else {
break;
}
}
let vowel = numbered.substr(consonant.length);
assert((!consonant || consonants[consonant]) && vowels[vowel]);
if (two_syllables[vowel]) {
const index = 'aeiouv'.indexOf(vowel[1]);
vowel = vowel[0] + vowel_to_tone[tone][index] + vowel.substr(2);
} else {
const index = 'aeiouv'.indexOf(vowel[0]);
assert(index >= 0);
vowel = vowel_to_tone[tone][index] + vowel.substr(1);
}
return consonant + vowel.replace('v', 'ü');
}
pinyin_util.tonePinyinToNumberedPinyin = (tone) => {
return pinyin_util.dropTones(tone, true /* append_number */);
}
export {pinyin_util};