Rev. 2.73

미국 샌프란시스코에서 열리는 WWDC(Worldwide Developers Conference) 08이 코앞으로 다가왔습니다. 현지시간 6월 9일 오전 9시, 한국시간은 10일 새벽 2시경에 시작합니다. 이번 행사에서 3G 아이폰이 윤곽을 드러낼 것으로 열려져 있죠. 벌써부터 가슴이 벅차오릅니다. 참관하지 못한 분들을 위해 스티브 잡스씨의 키노트를 실시간으로 스트리밍하거나 라이브 포스팅하겠다는 사이트들이 있어 알려드립니다. 대부분 영문 사이트들 입니다만, 얼마전에 만든 다국어 번역 북마크릿을 십분 활용해 보려고 합니다. :)

wwdc2008.jpg

Comments


Dion Almaer씨의 구글 AJAX Language API를 이용한 다국어 번역 북마크릿을 보고 한글로 번역되는 것도 있으면 좋겠다 싶어 만들어 보았습니다. 구글의 AJAX Language API는 총 39개국의 언어를 지원하며, 그중에서도 한국을 포함한 23개국 언어간 쌍방향 번역기능이 포함된 쓸만한 번역 엔진입니다. 번역하고자 하는 문자 영역을 드래그하여 선택한 후 북마크릿을 클릭하면 위 화면과 같은 번역 결과물을 출력합니다. 파이어폭스2, 3 RC에서 테스트 되었으며, 아쉽게도 IE계열 브라우저는 지원하지 않습니다. 자세한 특징은 다음과 같습니다.

  • 39개국 언어를 지원하는 구글 AJAX Language API를 사용함
  • 영어, 일본어, 프랑스어, 독일어, 중국어 등 총 23개국 언어 번역 지원
  • 번역 대상의 언어를 자동검출함으로 별도로 지정할 필요가 없음
  • 어느 사이트에서나 잘 보일수 있는 출력화면 최적화
  • 빠른 속도를 위해 별도의 자바스크립트 라이브러리(프레임웍)을 사용치 않음
  • 512바이트 단위로 분할 전송하여 장문 번역 가능(추가)
  • 장문인 경우 단어 단위로 계산하여 오역 발생 확률 감소(추가)
  • 줄바꿈 인식 및 HTML코드 탈출(추가)
  • 창의 크기가 윈도 크기를 넘긴 경우 스크롤바 활성(추가)
  • 상황별 오류 출력(추가)
  • 상황별 처리중 알리미 출력(추가)
  • 창 드래그 앤 드롭(추가 예정)

다국어 번역 북마크릿 - 이 링크를 브라우저의 북마크 도구모음에 추가하거나 북마크에 추가 하십시오.

if (!window.apiLoaded) {
  window.apiLoaded = function(text) {
    var link = false, next = null, language = 'ko';
    if (!text) {
      text = window.getSelection().toString().replace(/&/g, '&');
      text = text.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\n/g, '<br/>');
    } else link = true;

    if (text.length > 511) {
      var count = 0, words = text.split(' ');
      for (var i = 0; i < words.length; i++) {
        var l = words[i].length + 1;
        if (count + l > 500) {
          if (count > 511) count -= words[i-1].length + 1;
          break;
        }
        count += l;
      }
      next = text.substring(count + 1, text.length);
      text = text.substring(0, count);
    }

    var win = document.getElementById('__translationWindow');
    var img = document.getElementById('__translationWindowIcon');
    if (!link && win && win.style.display != 'none')
      win.childNodes[1].innerHTML = 'Translating...';
    else if (!img) {
      img = document.createElement('img');
      img.id = '__translationWindowIcon';
      img.src = "http://www.google.com/favicon.ico";
      img.setAttribute('style', 'top:10px;right:10px;position:fixed;z-index:999998');
      document.body.appendChild(img);
    } else img.style.display = 'block';

    var getLang = function(lang) {
      for (var l in google.language.Languages)
        if (google.language.Languages[l] == lang) return l.toLowerCase();
      return lang;
    };

    var error = function(text, lang) {
      if (lang) lang = 'guessing the language: ' + getLang(lang);
      text = 'No translation found for "' + text + '" ' + lang;
      return translationWindow(text, null, link, img, win);
    };

    if (!text) return error('');
    google.load('language', '1', {'callback': function() {
      google.language.detect(text, function(d) {
        if (!d.error && d.language) {
          google.language.translate(text, d.language, language, function(t) {
            if (t.translation) {
              translationWindow(t.translation, getLang(d.language), link, img, win);
              if (next) apiLoaded(next);
            } else error(text, language);
          });
        } else error(text, '');
      });
    }});
  };
}

if (!window.translationWindow) {
  window.translationWindow = function(translation, language, link, img, win) {
    img.style.display = 'none';
    if (!win) {
      var ws = [
        'font-family:AppleGothic,Malgun Gothic,Gulim,Dotum', 'background:#eee',
        'width:300px', 'opacity:0.9', 'padding:1px', 'text-align:left', 'color:#333',
        'top:10px', 'right:10px', 'font-size:12px', 'overflow:auto', 'position:fixed',
        'border:3px solid #aaa', 'line-height:1.5', 'z-index:999999', 'display:block'
      ], ds = ['background:#bbb','padding:2px 4px'];

      win = document.createElement('div');
      win.id = '__translationWindow';
      win.onmouseover = function() { win.style.opacity='1'; };
      win.onmouseout  = function() { win.style.opacity='0.9'; };
      win.setAttribute('style', ws.join(';'));
      win.innerHTML = [
        '<div style="font-size:13px;font-weight:bold;margin-bottom:3px;'+ds.join(';')+'">', 
          '<img style="vertical-align:text-bottom;" src="' + img.src + '"/>',
          'Google Translate',
        '</div>',
        '<span></span>',
        '<div style="text-align:right;font-size:11px;margin-top:3px;'+ds.join(';')+'">',
        '</div>'].join('');

      var a = document.createElement('a');
      a.setAttribute('style', 'position:absolute;top:2px;right:7px;cursor:pointer;');
      a.innerHTML = 'x';
      a.onclick = function(){ win.style.display = 'none'; };
      win.firstChild.appendChild(a);

      document.body.appendChild(win);
    } else win.style.display = 'block';

    var span = win.childNodes[1];
    if (!link){
      if (!language) translation = '<span style="color:#f30">' + translation + "</span>";
      else win.lastChild.innerHTML = 'detected as ' + language;
      span.innerHTML = translation;
      win.style.bottom = '';
    } else {      
      span.innerHTML += ' ' + translation;
      if (window.innerHeight < win.offsetHeight) win.style.bottom = '10px';
    }
    return true;
  };
}

if (!window.google || (google && !google.language)) {
  var script = document.createElement('script');
  script.src = 'http://www.google.com/jsapi?callback=apiLoaded';
  script.type = 'text/javascript';
  document.getElementsByTagName('body')[0].appendChild(script);
} else apiLoaded();

void(0);

Javascript to URL Bookmarklet Encoder

만들다 보니 자바스크립트 코드를 URL 형태로 만들어주는 녀석이 필요해서 간단한 엔코더도 만들었습니다. 상단의 TEXTAREA에 자바스크립트 코드를 넣고 버튼을 누르면 북마크릿에 사용할 수 있는 URL형태로 변환해 줍니다. 좌측 버튼은 최소한의 코드 변환을 실행하고 우측 버튼은 웹 표준에 부합하는 링크용 코드로 변환합니다.

Comments