Ext JS - Learning Center

Tutorial:Localizing Ext (Korean)

From Learn About the Ext JavaScript Library

Jump to: navigation, search
Summary: 본 튜토리얼은 Ext를 어떻게 현지화(번역)하는지 알려 줍니다.
Author: Jozef Sakalos (번역:김재형)
Published: March 9, 2008
Ext Version: 2.0+
Languages: en.png Englishkr.png Koreancn.png Chinese

Contents

시작하기

여러분이 영문 튜토리얼을 읽을 수 있고 영문을 모두 이해 한다면 현지화(영문을 타 언어로 번역) 작업이 필요 없겠지요. 하지만 우리의 사용자, 관리자, 임원, 영업사원들은 Ext 어플리케이션을 자신들의 모국어로 사용하고 싶겠지요?

이제 현지화 방법을 살펴 봅시다.

쉽게 시작하기

만약 Ext 2.x 배포본의 디렉터리를 살펴보는 중이었다면 source/locale 디렉터리를 볼 수 있을 겁니다(SVN에서는 src/locale). 이 디렉터리는 Ext 클래스들을 위한 현지화 파일들을 담고 있는데 빡세게 분석하기 전에 간단히 파일들을 활용해 봅시다.

아래 예제는 Ext의 박스 내에서 현지화하는 코드를 포함하고 있는데, 각자 Ext가 설치된 위치에 맞추어 경로 수정을 해야 할겁니다. 지역(locale) 디렉터리의 경로를 꼼꼼히 확인하세요.

아래의 예제를 복사 & 붙여 넣기로 작성 후 서버의 알맞은 경로에 저장합니다:

주의 : 예제는 Firefox에서만 작동합니다. 이번 튜토리얼에서는 head내에서 동적 자바스크립트 인클루드를 사용해보려고 합니다. 실제 개발하는 어플리케이션에서 이런 테크닉을 사용할 수 없다면 대안으로 head내의 현지화 스크립트는 서버 측에서 생성하게 해야 합니다.

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-all.css">
    <script type="text/javascript" src="../ext/adapter/ext/ext-base.js"></script>
    <script type="text/javascript" src="../ext/ext-all-debug.js"></script>
    <script type="text/javascript">
 
    // decode language passed in url
    var locale = window.location.search 
                 ? Ext.urlDecode(window.location.search.substring(1)).locale 
                 : '';
 
    // append locale script to the head
    var head = Ext.fly(document.getElementsByTagName('head')[0]);
    if(locale) {
        Ext.DomHelper.append(head, {
             tag:'script'
            ,type:'text/javascript'
            ,src:'../ext/src/locale/ext-lang-' + locale + '.js'
        });
    }
 
    // create pre-configured example window extension class
    Ext.ns('Tutorial');
    Tutorial.LocalizationWin = Ext.extend(Ext.Window, {
        initComponent:function() {
            Ext.apply(this, {
                 width:500
                ,id:'winid'
                ,height:300
                ,layout:'fit'
                ,border:false
                ,closable:false
                ,title:Ext.get('title').dom.innerHTML
                ,items:[{
                     xtype:'form'
                    ,frame:true
                    ,defaultType:'textfield'
                    ,items:[{
                          xtype:'combo'
                         ,fieldLabel:'Select Language'
                         ,name:'locale'
                         ,store:new Ext.data.SimpleStore({
                             id:0
                            ,fields:['file', 'locale']
                            ,data:[
                                 ['cs', 'Czech']
                                ,['', 'English']
                                ,['fr', 'French']
                                ,['de', 'German']
                                ,['gr', 'Greece']
                                ,['hu', 'Hungarian']
                                ,['it', 'Italian']
                                ,['ja', 'Japaneese']
                                ,['pl', 'Polish']
                                ,['pt', 'Portugal']
                                ,['ru', 'Russian']
                                ,['sk', 'Slovak']
                                ,['es', 'Spanish']
                                ,['sv_SE', 'Swedish']
                                ,['tr', 'Turkish']
                            ]
                         })
                        ,listeners:{
                            select:{fn:function(combo){
                                window.location.search = '?' 
                                    + Ext.urlEncode({locale:combo.getValue()})
                                ;
                            }}
                        }
                        ,mode:'local'
                        ,editable:false
                        ,forceSelection:true
                        ,valueField:'file'
                        ,displayField:'locale'
                        ,triggerAction:'all'
                        ,value:locale
                     },{
                         fieldLabel:'Text Field'
                        ,allowBlank:false
                    },{
                         xtype:'datefield'
                        ,fieldLabel:'Date Field'
                        ,allowBlank:false
                    }]
                }]
            }); // eo apply
            Tutorial.LocalizationWin.superclass.initComponent.apply(this, arguments);
        } // eo function initComponent
    }); // eo Tutorial.LocalizationWin
 
Ext.BLANK_IMAGE_URL = '../ext/resources/images/default/s.gif';
Ext.onReady(function() {
    Ext.QuickTips.init();
    Ext.form.Field.prototype.msgTarget = 'side';
 
    // create example window
    var win = new Tutorial.LocalizationWin();
    win.show();
});
    </script>
    <title id="title">Localization Example</title>
</head>
<body>
</body>
</html>

예제 내에서 현지화는 ComboBox, TextField, DateField 와 같은 기본 Ext 컴포넌트에만 적용됩니다. 번역된 DatePicker와 유효성 검증 메시지를 만들어 봅시다.

어떻게 작동 하나요?

"Select Language" 콤보박스의 선택 값을 기준으로 Ext 지역(locale) 디렉터리내의 지역별 "lang"파일을 개별적으로 인클루드 하게 됩니다. (저는 예제에서 몇 가지 꽁수를 사용했는데, 일반적으론 head내의 <script>태그를 서버에서 생성되게 구성합니다.)

현지화 파일내부는?

현지화 파일내의 내용을 살펴봅시다; 이 비기를 습득하면 Ext뿐만 아니라 지구상의 모든 어플리케이션을 현지화 하는데 도움이 될 겁니다. 이제 불어로 번역된 DatePicker를 살펴봅니다:

if(Ext.DatePicker){
   Ext.override(Ext.DatePicker, {
      todayText         : "Aujourd'hui",
      minText           : "Cette date est antérieure à la date minimum",
      maxText           : "Cette date est postérieure à la date maximum",
      disabledDaysText  : "",
      disabledDatesText : "",
      monthNames        : Date.monthNames,
      dayNames          : Date.dayNames,
      nextText          : 'Mois suivant (CTRL+Flèche droite)',
      prevText          : "Mois précédent (CTRL+Flèche gauche)",
      monthYearText     : "Choisissez un mois (CTRL+Flèche haut ou bas pour changer d'année.)",
      todayTip          : "{0} (Barre d'espace)",
      okText            : "&#160;OK&#160;",
      cancelText        : "Annuler",
      format            : "d/m/y",
      startDay          : 1
   });
}

초기화 테스트 후 DatePicker가 생성되어 있으면(여러분들은 DatePicker 클래스를 사용하지 않는 Ext 어플리케이션을 만들 수도 있기 때문에 이렇게 설정하는 것입니다.) 몇몇 프로퍼티를 오버라이드하게 설정하여 간단히 영어 텍스트를 불어로 변경되게 하였습니다. Ext.override는 클래스의 원형(prototype)을 변경하는데 상단의 예제는 DatePicker의 인스턴스가 생성(create)되기 이전에 실행 됩니다.

어플리케이션 현지화

다시 예제 어플리케이션을 정리해봅시다. 대부분 정적(static) 텍스트를 제거하고 클래스 변수로 옮겼는데 그 결과는 아래와 같습니다:

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-all.css">
    <script type="text/javascript" src="../ext/adapter/ext/ext-base.js"></script>
    <script type="text/javascript" src="../ext/ext-all-debug.js"></script>
 
    <!-- Ext localization javascript -->
    <script type="text/javascript" id="extlocale"></script>
 
    <!-- Locale and example extension javascript -->
    <script type="text/javascript">
 
    // decode language passed in url
    var locale = window.location.search 
                 ? Ext.urlDecode(window.location.search.substring(1)).locale 
                 : ''
    ;
 
    // append locale script to the head
    var head = Ext.fly(document.getElementsByTagName('head')[0]);
    if(locale) {
        Ext.fly('extlocale').set({src:'../ext/src/locale/ext-lang-' + locale + '.js'});
    }
 
    // create pre-configured example window extension class
    Ext.ns('Tutorial');
    Tutorial.LocalizationWin = Ext.extend(Ext.Window, {
         titleText:'Localization Example'
        ,selectLangText:'Select Language'
        ,textFieldText:'Text Field'
        ,dateFieldText:'Date Field'
        ,initComponent:function() {
            Ext.apply(this, {
                 width:500
                ,id:'winid'
                ,height:300
                ,layout:'fit'
                ,border:false
                ,closable:false
                ,title:this.titleText
                ,items:[{
                     xtype:'form'
                    ,frame:true
                    ,defaultType:'textfield'
                    ,items:[{
                          xtype:'combo'
                         ,fieldLabel:this.selectLangText
                         ,name:'locale'
                         ,store:new Ext.data.SimpleStore({
                             id:0
                            ,fields:['file', 'locale']
                            ,data:[
                                 ['cs', 'Czech']
                                ,['', 'English']
                                ,['fr', 'French']
                                ,['de', 'German']
                                ,['gr', 'Greece']
                                ,['hu', 'Hungarian']
                                ,['it', 'Italian']
                                ,['ja', 'Japaneese']
                                ,['pl', 'Polish']
                                ,['pt', 'Portugal']
                                ,['ru', 'Russian']
                                ,['sk', 'Slovak']
                                ,['es', 'Spanish']
                                ,['sv_SE', 'Swedish']
                                ,['tr', 'Turkish']
                            ]
                         })
                        ,listeners:{
                            select:{fn:function(combo){
                                window.location.search = '?' 
                                    + Ext.urlEncode({locale:combo.getValue()})
                                ;
                            }}
                        }
                        ,mode:'local'
                        ,editable:false
                        ,forceSelection:true
                        ,valueField:'file'
                        ,displayField:'locale'
                        ,triggerAction:'all'
                        ,value:locale
                     },{
                         fieldLabel:this.textFieldText
                        ,allowBlank:false
                    },{
                         xtype:'datefield'
                        ,fieldLabel:this.dateFieldText
                        ,allowBlank:false
                    }]
                }]
            }); // eo apply
            Tutorial.LocalizationWin.superclass.initComponent.apply(this, arguments);
        } // eo function initComponent
    }); // eo Tutorial.LocalizationWin
    </script>
 
    <!-- Application localization javascript -->
    <script type="text/javascript" id="applocale"></script>
 
    <!-- Set src for application localization javascript -->
    <script>
    if(locale) {
        Ext.fly('applocale').set({src:'app-lang-' + locale + '.js'});
    }
    </script>
 
    <!-- Main application -->
    <script type="text/javascript">
    Ext.BLANK_IMAGE_URL = '../ext/resources/images/default/s.gif';
    Ext.onReady(function() {
        Ext.QuickTips.init();
        Ext.form.Field.prototype.msgTarget = 'side';
 
        // create example window
        var win = new Tutorial.LocalizationWin();
        win.show();
    });
    </script>
    <title id="title">Localization Example</title>
</head>
<body>
</body>
</html>

그리고 마지막 단계로 어플리케이션 현지화(번역, 언어) 파일을 생성해야 합니다. 저는 슬로바키아 말을 할 줄 아니까 슬로바키아 언어 파일인 app-lang-sk.js로 하는데 여러분은 각자 자국의 언어로 작성하시면 됩니다.(파일을 html코드 내 설정경로와 동일한 디렉터리에 두던가 아니면 html코드 내 설정경로를 파일경로에 맞게 수정하세요):

/**
 * Slovak localization file of Localization Tutorial Example Window
 */
if(Tutorial.LocalizationWin) {
    Ext.override(Tutorial.LocalizationWin, {
         titleText:'Príklad lokalizácie'
        ,selectLangText:'Zvoľ jazyk'
        ,textFieldText:'Textové pole'
        ,dateFieldText:'Dátumové pole'
    });
}

고급 힌트

다음과 같은 Ext 현지화의 기본 원리를 이해하는 것이 중요합니다: 모든 텍스트를 퍼블릭 클래스 변수에 담고 번역된 버전에서는 이 값들을 오버라이드 한다.

고수 개발자들은 현지화 파일의 작성, 유지보수, 배포와 같은 복잡한 작업처리를 쉽게하기 위해 GNU gettext와 같은 번역 인프라와 서버를 구성합니다. 이런 분들은 gettext를 이용하여 서버 측에서 동적으로 현지화 파일을 생성하는 방식을 사용할 것을 권장합니다.

이 방법의 주된 장점은 중앙의 번역 파일(*.po)로 클라이언트와 서버 양쪽에 적용시킨다는 것이지요.

본 주제가 화제가 되고 여러분의 많은 흥미를 일으켜서 제가 고급 현지화 튜토리얼을 작성하는 기회를 가져 보길 기원합니다.


Further reading:

  • This page was last modified 16:46, 20 April 2008.
  • This page has been accessed 1,541 times.