User:Ed Poor/hiragana.js

// Converts Hiragana text to Romaji

// Includes an optional self-test

var bugs = false;

function test {

assertEquals( kanaToRomaji('か'), 'ka'); assertEquals( kanaToRomaji('と'), 'to');

assertEquals( hiraganaToRomaji('ちば'), 'Chiba'); assertEquals( hiraganaToRomaji('まって'), 'matte'); assertEquals( hiraganaToRomaji('いっぱい'), 'ippai'); assertEquals( hiraganaToRomaji('いっ'), 'iっ'); assertEquals( hiraganaToRomaji('きょこ'), 'Kyoko'); assertEquals( hiraganaToRomaji('しゃい'), 'shai'); assertEquals( hiraganaToRomaji('いらっしゃい'), 'irasshai'); // buggy assertEquals( hiraganaToRomaji('まっちがった'), 'matchigatta'); // buggy if (!bugs) debugPrint("Okay"); }

function hiraganaToRomaji(kanaText) {

//for each Japanese syllable that has a conversion, use it. //any characters that can't be converted, just pass them through.

var result = ""; while (kanaText.length > 0) { var romaji; var kanaProcessed; var kana = kanaText.charAt(0); var follower = kanaText.charAt(1); if (isSokuonPair(kana, follower)) {

// SMALL TSU is called a 'sokuon' and it doubles or strengthens the next kana's 'consonant' //Find the first letter of the next kana's romaji equivalent, and pass that along. // Example: T + TE or P + PA or M + MA /*     romaji = getSokuonSyllable(follower); kanaProcessed = 2; romaji = getSokuonConsonant(follower); kanaProcessed = 1; } else if ( isComboSyllable(kana, follower) ) { var prefix = kanaToRomaji(kana).charAt(0); romaji = prefix + kanaToRomaji(follower); kanaProcessed = 2; } else { romaji = kanaToRomaji( kana ); kanaProcessed = 1; }   romaji = kanaToHepburn( romaji );   // comment out if you don't want Hepburn romanization result += romaji; // Dispose of processed characters. kanaText = kanaText.substring(kanaProcessed); }   return result; }

function isComboSyllable(leader, follower) {

var leaderRomaji = kanaToRomaji(leader); var leaderVowel = leaderRomaji.charAt(leaderRomaji.length - 1); // last char must be vowel i   if ( leaderVowel != 'i' ) return false; else return isSmallYaYuYo(follower); }

function isSmallYaYuYo(kana) { var littleVowels = 'ゃゅょ' ; return (isNeedleInHaystack(kana, littleVowels)); }

function isSokuonPair(leader, follower) { // Must start with small tsu if (leader != 'っ') return false; if (follower.length == 0) return false; // only for K, T, S, or P   var followerConsonant = kanaToRomaji( follower ).charAt(0); var allowable = 'ktsp'; return allowable.indexOf(followerConsonant) >= 0; }

function getSokuonSyllable(kana) {

var romaji = kanaToRomaji(kana); var consonant = romaji.charAt(0); return consonant + romaji; }

function getSokuonConsonant(kana) {

var romaji = kanaToRomaji(kana); return romaji.charAt(0); }

// Convert one kana to its plain romaji equivalent

function kanaToRomaji(text) {

var myArray = [ ['ぁ', 'a'], ['あ', 'a'], ['ぃ', 'i'], ['い', 'i'], ['ぅ', 'u'], ['う', 'u'], ['ぇ', 'e'], ['え', 'e'], ['ぉ', 'o'], ['お', 'o'], ['か', 'ka'], ['が', 'ga'], ['き', 'ki'], ['ぎ', 'gi'], ['く', 'ku'], ['ぐ', 'gu'], ['け', 'ke'], ['げ', 'ge'], ['こ', 'ko'], ['ご', 'go'], ['さ', 'sa'], ['ざ', 'za'], ['し', 'si'], ['じ', 'zi'], ['す', 'su'], ['ず', 'zu'], ['せ', 'se'], ['ぜ', 'ze'], ['そ', 'so'], ['ぞ', 'zo'], ['た', 'ta'], ['だ', 'da'], ['ち', 'ti'], ['ぢ', 'di'], //     ['っ', 'sokuon'], // handled differently ['つ', 'tu'], ['づ', 'du'], ['て', 'te'], ['で', 'de'], ['と', 'to'], ['ど', 'do'], ['な', 'na'], ['に', 'ni'], ['ぬ', 'nu'], ['ね', 'ne'], ['の', 'no'], ['は', 'ha'], ['ば', 'ba'], ['ぱ', 'pa'], ['ひ', 'hi'], ['び', 'bi'], ['ぴ', 'pi'], ['ふ', 'hu'], ['ぶ', 'bu'], ['ぷ', 'pu'], ['へ', 'he'], ['べ', 'be'], ['ぺ', 'pe'], ['ほ', 'ho'], ['ぼ', 'bo'], ['ぽ', 'po'], ['ま', 'ma'], ['み', 'mi'], ['む', 'mu'], ['め', 'me'], ['も', 'mo'], ['ゃ', 'ya'], ['や', 'ya'], ['ゅ', 'yu'], ['ゆ', 'yu'], ['ょ', 'yo'], ['よ', 'yo'], ['ら', 'ra'], ['り', 'ri'], ['る', 'ru'], ['れ', 're'], ['ろ', 'ro'], ['ゎ', 'wa'], ['わ', 'wa'], ['ゐ', 'wi'], ['ゑ', 'we'], ['を', 'wo'], ['ん', 'n'], ['ヴ', 'vu'] ];

for (var i = 0; i < myArray.length; i++) { var kana = myArray[ i ] [ 0 ]; if (kana == text) { return myArray[ i ] [ 1 ]; }   }    return text; }

// These "eat" the Y from YA, YU, YO. hungryYoonArray = [ 'SHI', 'CHI', 'JI' ];

function kanaToHepburn(romaji) {

var result = romaji; // Look for Hepburn variations. var hepburn = [

['si', 'shi'], ['zi', 'ji'], ['ti', 'chi'], ['di', 'ji'], ['tu', 'tsu'], ['du', 'zu'], ['hu', 'fu'], ['sya', 'sha'], ['syu', 'shu'], ['syo', 'sho'], ['zya', 'ja'], ['zyu', 'ju'], ['zyo', 'jo'], ['tya', 'cha'], ['tyu', 'chu'], ['tyo', 'cho'] ];   for (var i = 0; i < hepburn.length; i++) { var myHep = hepburn[ i ] [ 0 ]; if (myHep == romaji) { result = hepburn[ i ] [ 1 ]; break; }   }    return result; }

function isNeedleInHaystack(needle, haystack) { return haystack.indexOf(needle) != -1; }

//////////// UTILITIES ////////////////////////////////

function debugPrint(blurb) { document.write(blurb + ''); }

function assertEquals(first, second) {

if (first.toUpperCase == second.toUpperCase) { return; } else { bugs = true; var problem = first + " should equal " + second; document.write(problem + ""); throw new Error(problem); } }

function assert(myBool) {

if (myBool) return; else ("Error found"); }