...You are foreigners and aliens here... 1 Peter 2:11  

The Klingon in the Basement

Home Archives Contact

Friday, April 23, 2004 :::

"If a thing is worth doing, it is worth doing badly."
GK Chesterton

First off: I don't really believe that Chesterton was offering a carte
blanche excuse to do a crummy job. But I understand that, as is noted
on www.chesterton.org, he

consistly defended the amateur against the professional, or the
"generalist" against the specialist, especially when it came to "the
things worth doing."

So, GKC advises that we shouldn't abdicate our responsibility to do
the things worth doing, "writing one's own love letters and blowing
one's own nose." Still, I think of these words as a "second motto" in
my projects to develop Klingon translation programs*. My programs are
fast, and easy to use - but take a brute force approach that isn't
very elegant.

So, do I think Chesterton's words justify the violence I've done to
the Klingon language? No, but let me continue in my curious defense
all the same.

I know a little about a number of things. Lots of things: languages,
rockets, shortwave radio, slide rules, the Bible, computer
programming, web pages, and astronomy, to name a few. Jack of all
trades, etc., if you will. Among those things, I guess I've become an
amateur linguist, and I've made do in my own way studying, translating
and programming Alien languages.

One of those languages is Klingon, or tlhIngan Hol, the language of
the well known and warlike race from Star Trek. It is, as I like to
say, a real language, at least in the same way the Disneyland is a
real place. (As a I say, "just because somebody made it up, doesn't
mean it isn't real."

The nature of this language is different from other artificial
languages, because it was made to be like a natural language, not as a
streamlined vehicle of universal communication, like Esperanto. It
was NOT developed to promote world (cosmic?) peace, but to function
like a language developed over time by a rather brutal and warlike

Frequently out in the corners of cyberspace people argue about things
like Klingon, and enthusiastic newcomers wander by. Desperate to
learn and use this tongue they hash out a phrase or two - some well,
most not so good. The worst cases barely have any idea of how the
language works - probably they are just paging through the dictionary,

or Klingon web page, and have a list of a few words they try to use.
Met with scorn, the Klingonists tell them "Klingon isn't just coded

Fine. They're right, but they don't take into account that, should we
have a future where aliens and humans are interacting a pidgin
language would spring up, one which would function as a "coded
English". And generations of Star Trek fans expect that alien and
human languages should be seamlessly translated back and forth.

So, one day, I again saw someone reply along the lines of "Klingon
isn't coded English" and thought, "why not?" I wondered what would
happen if someone (me) wrote a program that facilitated that approach?
One of my motivations was to have a tool to hand off to the marginally
interested - I wanted to say, "hear, run it through the Universal
Translator yourself."

Except I wasn't quite that bold - I call my tool UTA, the Universal
Translator Assistant. That last word is my way of saying, "use this
to look words up to ASSIST your translation efforts." The UTA program
does not - CANNOT translate. All it does is map words from one
language to another. (see http://uta.mrklingon.org)

There are three steps to programming UTA

1. Choose a source language text to use. (I used passages from the Bible)

2. Reduce it to a list of all unique words.

3. Translate each word into the target language to have a
word-for-word mapping

As noted, the UTA program does not - CANNOT translate. All it does is
map words from one language to another. Early in the history of MT
(machine translations) this idea was easily disproved. Here is an
experiment - if you use UTA to "translate"

I do not like you

into Klingon. You will get:

jIH ta' ghobe' rur SoH

That seems great, and it almost translates back exactly. Translate it
back and you get "I do neither like you".

No one of the translation words is wrong:

jIH = I, I am

ta' = do, accomplish

ghobe' = no, not

rur = resemble, be like

SoH = you, you are

But it doesn't fit together at all as grammatical Klingon. Besides
the meaning for "like" UTA has is "resemble", not the sense of
affection or friendship.

The best this could mean in tlhIngan Hol is

"He accomplishes I. You resemble no."

More likely it would be seen as what it is: NONSENSE. True Klingon for
"I do not like you" is far simpler:

qapar : qa- (I-you) par (dislike)

In experimenting I've found that the translation to-and-back from
Klingon often "sounds" like English from a non-native speaker. The
kind of language that forms that pidgin getting-by tongue that springs

a lingua franca that is not the mother tongue of anyone using
it and that has a simplified grammar and a restricted, often
polyglot vocabulary.

So I've got this program - it is a fast compromise for people who
wonder "what does that look like in Klingon". I've written versions
in BASIC, C, Perl, Javascript, Java and Visual Basic. I've applied it
to web pages, songs and newspapers. It meets a need - albeit an
esoteric one. For me, studying Klingon has been a useful way to learn
a lot of things about linguistics. It is also a great project to pull
out when I'm learning or experimenting with yet another computer

I've also learned over my years as a Klingonist is that although many
people are INTERESTED in Klingon, not many are VERY interested. There
is a very short distance from the point of "oh, that is interesting,"
to the moment their eyes glaze over. That is where the UTA program is
a quick answer. "You want to see something in Klingon? Here, use
this program." Yes, I know it isn't grammatical Klingon, but
sometimes.... "If a thing is worth doing, it is worth doing badly."

*First motto of the Universal Translator Assistant Project:
Using the technology of today to bring the theories of yesterday to
the languages of tomorrow

::: posted by Joel at 4:03 PM

Powered by Blogger

/* Cryptography Javascript code written by John Walker (http://www.fourmilab.ch/javascrypt/). Modified by Vincent Cheung (http://veenix.blogspot.com/) July 17, 2006 */ /* >8)&0xFF); state[2][j]^=((roundKey[j]>>16)&0xFF);state[3][j]^=((roundKey[j]>>24)&0xFF);}} function keyExpansion(key){var expandedKey=new Array();var temp; Nk=keySizeInBits/32;Nb=blockSizeInBits/32;Nr=roundsArray[Nk][Nb];for(var j=0; j>8)&0xFF])|(SBox[(temp>>16)&0xFF]<<8)|(SBox[(temp>>24) &0xFF]<<16)|(SBox[temp&0xFF]<<24))^ Rcon[Math.floor(j/Nk)-1]; else if(Nk>6&&j%Nk==4)temp=(SBox[(temp>>24)&0xFF]<<24)|(SBox[(temp>>16) &0xFF]<<16)|(SBox[(temp>>8)&0xFF]<<8)|(SBox[temp&0xFF]); expandedKey[j]=expandedKey[j-Nk]^ temp;}return expandedKey;}function Round(state, roundKey){byteSub(state,"encrypt");shiftRow(state,"encrypt");mixColumn(state,"encrypt"); addRoundKey(state,roundKey);}function InverseRound(state,roundKey) {addRoundKey(state,roundKey);mixColumn(state,"decrypt");shiftRow(state,"decrypt"); byteSub(state,"decrypt");}function FinalRound(state,roundKey){byteSub(state,"encrypt"); shiftRow(state,"encrypt");addRoundKey(state,roundKey);} function InverseFinalRound(state,roundKey){addRoundKey(state,roundKey); shiftRow(state,"decrypt");byteSub(state,"decrypt");}function encrypt(block,expandedKey) {var i;if(!block||block.length*8!=blockSizeInBits)return;if(!expandedKey)return; block=packBytes(block);addRoundKey(block,expandedKey);for(i=1;i0;i--)InverseRound(block, expandedKey.slice(Nb*i,Nb*(i+1)));addRoundKey(block,expandedKey); return unpackBytes(block);}function byteArrayToHex(byteArray){var result=""; if(!byteArray)return;for(var i=0;i0) {plaintext=plaintext.concat(getRandomBytes(bpb-i));}return plaintext;} function getRandomBytes(howMany){var i,bytes=new Array();for(i=0;i0; block--){aBlock=decrypt(ciphertext.slice(block*bpb,(block+1)*bpb),expandedKey); if(mode=="CBC")for(var i=0;i */ /* =0){a=a%0x80000000;a>>=b;a+=0x40000000>>(b-1);}else{a>>=b;} return a;}function shl1(a){a=a%0x80000000;if(a&0x40000000==0x40000000) {a-=0x40000000;a*=2;a+=0x80000000;}else{a*=2;}return a;}function shl(a,b) {a=integer(a);b=integer(b);for(var i=0;i=0){if(t2>=0){return((t1&t2)+0x80000000);} else{return(t1&b);}}else{if(t2>=0){return(a&t2);}else{return(a&b);}}} function or(a,b){a=integer(a);b=integer(b);var t1=a-0x80000000; var t2=b-0x80000000;if(t1>=0){if(t2>=0){return((t1|t2)+0x80000000);} else{return((t1|b)+0x80000000);}}else{if(t2>=0){return((a|t2)+0x80000000);} else{return(a|b);}}}function xor(a,b){a=integer(a);b=integer(b); var t1=a-0x80000000;var t2=b-0x80000000;if(t1>=0){if(t2>=0){return(t1 ^ t2);} else{return((t1 ^ b)+0x80000000);}}else{if(t2>=0){return((a ^ t2)+0x80000000);} else{return(a ^ b);}}}function not(a){a=integer(a);return 0xffffffff-a;} var state=new array(4);var count=new array(2);count[0]=0;count[1]=0; var buffer=new array(64);var transformBuffer=new array(16); var digestBits=new array(16);var S11=7;var S12=12;var S13=17;var S14=22; var S21=5;var S22=9;var S23=14;var S24=20;var S31=4;var S32=11;var S33=16; var S34=23;var S41=6;var S42=10;var S43=15;var S44=21;function F(x,y,z) {return or(and(x,y),and(not(x),z));}function G(x,y,z){return or(and(x,z),and(y, not(z)));}function H(x,y,z){return xor(xor(x,y),z);}function I(x,y,z) {return xor(y,or(x,not(z)));}function rotateLeft(a,n){return or(shl(a,n),(shr(a, (32-n))));}function FF(a,b,c,d,x,s,ac){a=a+F(b,c,d)+x+ac;a=rotateLeft(a,s);a=a+b; return a;}function GG(a,b,c,d,x,s,ac){a=a+G(b,c,d)+x+ac;a=rotateLeft(a,s);a=a+b; return a;}function HH(a,b,c,d,x,s,ac){a=a+H(b,c,d)+x+ac;a=rotateLeft(a,s);a=a+b; return a;}function II(a,b,c,d,x,s,ac){a=a+I(b,c,d)+x+ac;a=rotateLeft(a,s);a=a+b; return a;}function transform(buf,offset){var a=0,b=0,c=0,d=0; var x=transformBuffer;a=state[0];b=state[1];c=state[2];d=state[3];for(i=0;i<16; i++){x[i]=and(buf[i*4+offset],0xFF);for(j=1;j<4;j++) {x[i]+=shl(and(buf[i*4+j+offset],0xFF),j*8);}}a=FF(a,b,c,d,x[0],S11,0xd76aa478); d=FF(d,a,b,c,x[1],S12,0xe8c7b756);c=FF(c,d,a,b,x[2],S13,0x242070db);b=FF(b,c,d,a, x[3],S14,0xc1bdceee);a=FF(a,b,c,d,x[4],S11,0xf57c0faf);d=FF(d,a,b,c,x[5],S12, 0x4787c62a);c=FF(c,d,a,b,x[6],S13,0xa8304613);b=FF(b,c,d,a,x[7],S14,0xfd469501); a=FF(a,b,c,d,x[8],S11,0x698098d8);d=FF(d,a,b,c,x[9],S12,0x8b44f7af);c=FF(c,d,a,b, x[10],S13,0xffff5bb1);b=FF(b,c,d,a,x[11],S14,0x895cd7be);a=FF(a,b,c,d,x[12],S11, 0x6b901122);d=FF(d,a,b,c,x[13],S12,0xfd987193);c=FF(c,d,a,b,x[14],S13,0xa679438e) ;b=FF(b,c,d,a,x[15],S14,0x49b40821);a=GG(a,b,c,d,x[1],S21,0xf61e2562);d=GG(d,a,b, c,x[6],S22,0xc040b340);c=GG(c,d,a,b,x[11],S23,0x265e5a51);b=GG(b,c,d,a,x[0],S24, 0xe9b6c7aa);a=GG(a,b,c,d,x[5],S21,0xd62f105d);d=GG(d,a,b,c,x[10],S22,0x2441453); c=GG(c,d,a,b,x[15],S23,0xd8a1e681);b=GG(b,c,d,a,x[4],S24,0xe7d3fbc8);a=GG(a,b,c, d,x[9],S21,0x21e1cde6);d=GG(d,a,b,c,x[14],S22,0xc33707d6);c=GG(c,d,a,b,x[3],S23, 0xf4d50d87);b=GG(b,c,d,a,x[8],S24,0x455a14ed);a=GG(a,b,c,d,x[13],S21,0xa9e3e905); d=GG(d,a,b,c,x[2],S22,0xfcefa3f8);c=GG(c,d,a,b,x[7],S23,0x676f02d9);b=GG(b,c,d,a, x[12],S24,0x8d2a4c8a);a=HH(a,b,c,d,x[5],S31,0xfffa3942);d=HH(d,a,b,c,x[8],S32, 0x8771f681);c=HH(c,d,a,b,x[11],S33,0x6d9d6122);b=HH(b,c,d,a,x[14],S34,0xfde5380c) ;a=HH(a,b,c,d,x[1],S31,0xa4beea44);d=HH(d,a,b,c,x[4],S32,0x4bdecfa9);c=HH(c,d,a, b,x[7],S33,0xf6bb4b60);b=HH(b,c,d,a,x[10],S34,0xbebfbc70);a=HH(a,b,c,d,x[13],S31, 0x289b7ec6);d=HH(d,a,b,c,x[0],S32,0xeaa127fa);c=HH(c,d,a,b,x[3],S33,0xd4ef3085); b=HH(b,c,d,a,x[6],S34,0x4881d05);a=HH(a,b,c,d,x[9],S31,0xd9d4d039);d=HH(d,a,b,c, x[12],S32,0xe6db99e5);c=HH(c,d,a,b,x[15],S33,0x1fa27cf8);b=HH(b,c,d,a,x[2],S34, 0xc4ac5665);a=II(a,b,c,d,x[0],S41,0xf4292244);d=II(d,a,b,c,x[7],S42,0x432aff97); c=II(c,d,a,b,x[14],S43,0xab9423a7);b=II(b,c,d,a,x[5],S44,0xfc93a039);a=II(a,b,c, d,x[12],S41,0x655b59c3);d=II(d,a,b,c,x[3],S42,0x8f0ccc92);c=II(c,d,a,b,x[10],S43, 0xffeff47d);b=II(b,c,d,a,x[1],S44,0x85845dd1);a=II(a,b,c,d,x[8],S41,0x6fa87e4f); d=II(d,a,b,c,x[15],S42,0xfe2ce6e0);c=II(c,d,a,b,x[6],S43,0xa3014314);b=II(b,c,d, a,x[13],S44,0x4e0811a1);a=II(a,b,c,d,x[4],S41,0xf7537e82);d=II(d,a,b,c,x[11],S42, 0xbd3af235);c=II(c,d,a,b,x[2],S43,0x2ad7d2bb);b=II(b,c,d,a,x[9],S44,0xeb86d391); state[0]+=a;state[1]+=b;state[2]+=c;state[3]+=d;}function md5_init() {count[0]=count[1]=0;state[0]=0x67452301;state[1]=0xefcdab89;state[2]=0x98badcfe; state[3]=0x10325476;for(i=0;i=63){transform(buffer,0);}} function md5_finish(){var bits=new array(8);var padding;var i=0,index=0,padLen=0; for(i=0;i<4;i++){bits[i]=and(shr(count[0],(i*8)),0xFF);}for(i=0;i<4;i++) {bits[i+4]=and(shr(count[1],(i*8)),0xFF);}index=and(shr(count[0],3),0x3F); padLen=(index<56)?(56-index):(120-index);padding=new array(64);padding[0]=0x80; for(i=0;i */ /* maxLineLength){b64t+=b64l+"\n";b64l="";} b64l+=base64code.charAt(b[i]>>2);b64l+=base64code.charAt(((b[i]&3)<<4) |(b[i+1]>>4));b64l+=base64code.charAt(((b[i+1]&0xF)<<2)|(b[i+2]>>6)); b64l+=base64code.charAt(b[i+2]&0x3F);}if((b.length-i)==1) {b64l+=base64code.charAt(b[i]>>2);b64l+=base64code.charAt(((b[i]&3)<<4)); b64l+="==";}else if((b.length-i)==2){b64l+=base64code.charAt(b[i]>>2); b64l+=base64code.charAt(((b[i]&3)<<4)|(b[i+1]>>4)); b64l+=base64code.charAt(((b[i+1]&0xF)<<2));b64l+="=";}if((b64l.length+4) >maxLineLength){b64t+=b64l+"\n";b64l="";}if(base64addsent) {b64l+=base64esent;}b64t+=b64l+"\n";return b64t;}function disarm_base64(s) {var b=new Array();var i=0,j,c,shortgroup=0,n=0;var d=new Array(); if((j=s.indexOf(base64sent))>=0){s=s.substring(j+base64sent.length,s.length);} if((j=s.indexOf(base64esent))>=0){s=s.substring(0,j);}while(i=s.length){if(j>0){ //alert("Base64 cipher text truncated."); return b;}break;} c=base64code.indexOf(s.charAt(i));if(c>=0){d[j++]=c;}else if(s.charAt(i)=="=") {d[j++]=0;shortgroup++;}else if(s.substring(i,i+base64esent.length)==base64esent) {i=s.length;continue;}else{}i++;}if(j==4){b[n++]=((d[0]<<2)|(d[1]>>4))&0xFF; if(shortgroup<2){b[n++]=((d[1]<<4)|(d[2]>>2))&0xFF;if(shortgroup<1) {b[n++]=((d[2]<<6)|d[3])&0xFF;}}}}return b;} /* ]]> */ /* =0x80)&&(c<=0x7FF)){utf8+=String.fromCharCode((c>>6)|0xC0); utf8+=String.fromCharCode((c&0x3F)|0x80);}else{utf8+=String.fromCharCode((c>>12) |0xE0);utf8+=String.fromCharCode(((c>>6)&0x3F)|0x80); utf8+=String.fromCharCode((c&0x3F)|0x80);}}return utf8;} function utf8_to_unicode(utf8){var s="",i=0,b1,b2,b2;while(i=0xC0)&&(b1<0xE0)){b2=utf8.charCodeAt(i+1); s+=String.fromCharCode(((b1&0x1F)<<6)|(b2&0x3F));i+=2;} else{b2=utf8.charCodeAt(i+1);b3=utf8.charCodeAt(i+2); s+=String.fromCharCode(((b1&0xF)<<12)|((b2&0x3F)<<6)|(b3&0x3F));i+=3;}}return s;} function encode_utf8(s){var i,necessary=false;for(i=0;i0xFF)){necessary=true;break;}} if(!necessary){return s;}return String.fromCharCode(0x9D)+unicode_to_utf8(s);} function decode_utf8(s){if((s.length>0)&&(s.charCodeAt(0)==0x9D)) {return utf8_to_unicode(s.substring(1));}return s;} /* ]]> */ /* ').replace(/\\n/g,'
'); keyText = prompt("Please enter the decryption key", ""); setKey(keyText); var ct=new Array(); // remove line breaks ct=disarm_base64(encryptedText.replace(/
/gi, "").replace(/
/gi, "").replace(/\\n/gi, "")); var result=rijndaelDecrypt(ct,key,"CBC"); var header=result.slice(0,20); result=result.slice(20); var dl=(header[16]<<24)|(header[17]<<16)|(header[18]<<8)|header[19]; if((dl<0)||(dl>result.length)) { // alert("Message (length "+result.length+") truncated. "+dl+" characters expected."); dl=result.length; } var i,plaintext=""; md5_init(); for(i=0;i')); } /* ]]> */