본문 바로가기
Programming

i18n

by homecafe 2009. 10. 15.

Overview
Mobile I18N API를 정의함. J2ME Optional Package.
API that allow MIDP application developers to internationalize thir MIDP app.
date, time, numbers and currency amount에 대한 locale-specific formatting을 제공.

application specific / device specific resource , locale-specific collation of string

MIDP/CLDC기반이지만 CDC도 사용가능,

javax.microedition.global 패키지에 포함됨.

- Goal

MIDP/CLDC환경에서 desktop의 J2SE와 비슷한 환경을 제공, compact하고 generic한 api를 제공하도록 설계.

- System requirements

CLDC 1.1 혹은 이후버전이어야 하고, (fp numeric format을 포함해야 하므로)
input stream에 "mark and reset"이 지원되어야함.
MIDP 는 2.0 이후로 사용되어야함. microedition.locale을 포함. 정확하게는 1.0에 locale-specific manner로 common data item을 다룰수 있는
ui component를 포함해야함. UTF-8을 지원해야함.

- Version information

App은 Mobile I18N API를 device에서 제공해야함. microedition.global.version property "1.0" string을 리턴. API가 제공되지 않으면 "null"

- Implementation notes

CLDR (Common Locale Data Repository)

- Locales

  locale은 language, country or region의 조합.
  data포맷 변경, 스트링 변경등 다른 리소스사이에 차이를 구분하는데 사용.

- Locale identifiers

locale identifier는 simple string을 이용. empty string이 아니면 MIDP 2.0 spec의 chapter 5에서 locale identifier의 format을 따른다.
MIDP 2.0 locale identifier는 ISO 639-1 two-letter language code와 ISO 3166-1 two-leter country code와 다양한 코드로 구성됨. value가 non-null이면
오직 language code만 mandatory임.

API에의해 다뤄지는 application resource file에 관해서, locale 식별자로써 빈 스트링은 은 특별한 의미를 가지는데, "Resource file" section에서 다룸.
data item의 포맷팅이나 스트링 소팅할때 빈 로케일은 locale-neutral behavior ..?

j2se와의 robustness및 호환성에 대해서, 파라미터로서 locale 식별자를 가지는 method는 _와 -를 허용해야한다. 그러나 프로그래머는 -만 사용해야 한다.

특별히 정해지지 않으면 이 API에서 많은 클래스들은 default로 microedition.locale 시스템 property의 값을 이용한다. MIDP spec은 null을 허용하는데, 몇몇 클래스는
이런 상황에서 locale-neutral behaviour로 되돌아간다.

- Resources

Resource는 localize된 application data이다. application이 run되면 현재 시스템의 locale setting과 application resource의 organization에 따라
같은 identifier로 다른 resource가 load된다. 각 리소스는 runtime에 리소스를 로딩할때 사용되는 id가 있다.

Mobile i18n API는 application resource와 device resource 2개의 다른 카테코리를 가진다. ResourceManager 클래스는 이 두리소스에 접근하는데 사용된다.
Application resource는 developer에의해 혹은 application과 함께 공금되는 반면 device resource는 device제조사에 의해 미리 만들어진다.

manufacturer에 따라 다양한 device resource 집합은 이 API범위가 아님. 대신 manufacturer는 application 개발자가 사용할 적절한 public resource와 식별자를 정의한다.
device의 storage format은 구현에 따름.

- Base names

application programmer는 base name을 이용해서 application resource와 연결하여 그룹을 지정할수 있다. non-empty string은 그들이 속한 application resource파일의
이름으로 사용된다. base name은 메뉴 command나 message같은 app developer가 원하는 이름어떤것이든 나타낼수 있다.

base name이 비어있으면, device resource를 나타낸다. 이 리소스에 대해서는 application resource file은 없으나, manufacturer-defined resource를 참고해야한다.

application developer는 base name에 사용되는 문자를 ascii 문자로 제한해야한다. jar 파일 spec에서 파일이름에 사용되는 caracter encoding에 대해서는 explicite
하게 언급하고 이지는 않지만, 많은 utility들은 non-ascii 문자와 문제가 있다.

- Application resource files
Application resource는 application의 jar파일에 저장되어야한다. spec에서 정하는 binary resource file포맷이어야한다.
JAR파일 내의 구조는 다음을 따라야한다. resource파일을 저장하기위한 '/global'이라는 디렉토리를 포함하고 있어야함. 이 디렉토리는 지원하는 locale을 위한
subdirectory를 포함해야한다. 디렉토리이름은 valid한 MIDP 2.0 locale identifier여야함.

locale에 스페시픽한 Resource file은 /global아래 대응되는 locale subdirectory안에 있어야한다. 공통 resource는 /global안에 있어야한다.
리소스파일의 이름은 'baseName.res' 형태여야하고, baseName은 ResourceManager 컨스트럭터에서 사용된다. 예를들어
locale이 en과 fi-FI로 지정된 resource file의 절대 path는 /global/en/Menus.res 혹은 /global/fi-FI/Menus.res처럼 될수있다.  이경우 common resource file
이름은 '/global/Common.res'가 될수 있다.

Jar file root
   ------------ global ------------ Common.res
                 |
                 +------- fi-FI --------- Menus.res, Labels.res
                 +--------en   ---------- Menus.res, Labels.res
                 +-------de-DE ----------- Menus.res, Labels.res

종종 one locale을 다른 locale로 변경하지 않ㅇ아도 되는 element를 함께 넣는것의 장점이 있다. 이를테면 바뀔수는 있지만 번역되지 않는것을 common resource 파일에 넣으면
storage를 줄일수 있다.

MIDP 2.0 spec에 따라, microedition.locale 시스템 property가 있으면, (non-null이면) language part를 포함해야만한다. 이 API에 공통 locale을 구현하는것은 MIDP 2.0
definition을 확장하여 empty locale identifier 포인트를 /global에 위치하도록 확장할수 있다. 이 파일은 같은 locale-specific resource처럼 같은 naming rule을 따라야한다.

이 리소스 추출 매커니즘은 resource inheritance를 따라야만한다. 만약 specified locale identifier를 사용하는 리소스가 발견되지 않으면, locale identifier가
삭제된 마지막 component를 다시 찾아야한다. 발견될때까지, 혹은 common locale에서 리소ㄱ스가 발견될때까지. inheritance 매커니즘의 in-depth description 는
Resourcemanager class description을 참조.

Jar내의 디렉토리와 파일이름은 대소문자를 구분한다.

- Enumerating supported resource locales
base name 이 제공하는 locale을 결정하기위해 getSupportedLocale method를 가짐. application resource를 위해 JAR 파일은 각 basename에 대해서 meta-info file을 가져야한다.
'global/_basename' (지원하는 locale을 적어주는듯함). meta-information mechanism은 JAR파일 내부의 resource file을 반복해서 찾는것을 피해줌.

각 meta-information file은 base name에 대응하는 지원되는 locale을 list함. file은 base name을 지원하는 locale의 locale identifier를 포함해야한다.
blank space (U+0020)으로구분함.
이 파일은 binary resource file과 함께 생성되어야한다.

만약 meta-information 파일이 JAR파일 내부에 실제 resource file과 일치하지 않으면, 결과는 ResourceManager를 instanciate를 시도할때 basename과 요청된 locale은
다음을 따라야한다.

-  만약 meta-information file이 locale을 list하는데, base name과 locale의 조합이 resource file을 갖지 않으면, ResourceException을 내고 error code로
NO_RESOURCES_FOR_BASE_NAME을 던져야한다.
- 만약 meta-information 파일이 locale을 리스트하지 않으면 UnSupportedLocaleException을 던진다. basename과 locale의 조합이 resource file이 존재해도.

예를들어, JAR 파일이 basename으로 Menus라는 리소스파일을, Finnish, Hungarian, Brazilian Portugues locale로 가지고 있으면, global/_Menus는 다음을 포함해야한다.
fi-FI hu-HU pt-BR

meta-info file의 값은 U+0022 QUOTATION MARK를 이용하여 "fi-FI"처럼될수도 있다. 만약 basename을 위한 common resource파일이 존재하면 file은 empty string을 포함해야한다.
이 empty string은 파일의 맨 처음값으로 quote되어야한다.
앞 예제에서 basename Menus가 common resource를 가지면 meta-information file _Menus 은 "" fi-FI hu-HU pt-BR 을 포함해야 한다.
이것은 "" "fi-FI" "hu-HU" "pt-BR" 과 같다.

만약 meta-infomation file이 정해진 basename을 찾지 못하면 getSupportedLocale method는 ResourceException을 METAFILE_NOT_FOUND 에러코드와 함께 던져야한다.

- Binary resource file format

이 section에서는 I18N API의 binary resource file format을 기술한다. 이 API를 이용하여 접근하기 위해서, application에 ship된 resource file은 이 포맷을 따라야만한다.(MUST)
리소스파일의 각 resource는 관련 ID를 가져야한다. 0x00000000부터 0x7FFFFFFF (inclusive)사이의 값이다. resource id는 하나의 resource file내에서 unique해야한다.
그러나 같은 ㄱesource ID가 다른 resource fileㅇ는 존재할수 있고, 같은 basename의 다른 locale에도 존재할수 있다. 이것은 ResourceManager class description 에서
다뤄지는 resource inheritance를 허용한다.

모든 resource는 byte arrary로 저장된다. 공통 리소스로 존재하는 string은 API에서 특별한 case이다.
string은 UTF-8로 encode되어야한다. 다른 resource는 raw data로 저장되고, data의 meaning은 application-spcific. 예를들어 PNG image data는 LCDUI Image class의
CreateImage() method로 넘겨질수있다.

resource file format은 다음으로 구성된다.
- 4 byte signature
- header 길이,
- file header,
- resourc data

signature의 첫바이트는 0xEE(238)여야한다. 2, 3번째바이트는 0x4D, 0x49 (M, I in UTF-8 encoding), 4째 바이트는 file format과  API version을 포함해야한다.
version의 상위 4비트는 major version을 나타내고, 하위 4비트는 minor version을 나타낸다. minor, major version은 API의 version을 따라야한다.
이를테면 API버전 (1.0)의 byte는 0x10임.

헤더길이는 byte로 표현되고, 길이는 4byte signature를 포함하지 않아야한다.

파일헤더는 64bit entry테이블을 포함하는데, 각 리소스당 한개임. entry는 다음 component를 하나의 값으로 묶는다: resource ID, resource type, 파일의 시작부터
리소스의 byte offset. 상위 32bit entry는 resource ID를 포함해야한다. 하위 32bit는 type과 offset을 묶어서 포함해야한다. 처음 8bit는 type 남은 24bit는
파일의 처음부터 byte offset을 나타냄. resource block의 길이는 byte offset으로 계산됨. table의 마지막 entry는 special , file의 마지막을 지나간부분을 가리킴.
이것은 마지막 실제 resource의 길이를 계산하기위해서만 사용된다.

   bits 63...32     bits 31...0
|----------------|---------------|
   resource ID   |   type offset
                 |----|----------|

zero-length resource는 미래 content를 위한 placeholder로서 리소스파일을 허용한다. 구현은 offset table의 entry에 리소스로 null을 리턴하면 안된다.
대신에 string resource는 empty string을 리턴해야한다. binary data는 empty byte array를 리턴해야한다.

만약 resourceManager구현이 resource 캐슁을 지원하면, 구현은 offset과 type을 table을 처음 구성될때 memory에 읽어야한다. 나중에는
구현은 또한 리소스를 읽는것을 cache할수도 있다. resource manager가 caching을 지원하도록 결정하기위해서 application은 isCaching메소드를  call할수도있다.
이 정보는 application자체가 리소스를 cache할것인지 아닌지를 결정하는데 사용될수도 있다.

application specific resource data는 resource id의 순서로 resource file에 나타난다. 그러나 resource ID 가 gap을 포함할경우 index table은 sparse array가 될수 있다.
이것은 구현이 단지 index를 이용하여 처음부터 다시 파일을 읽지않고, resource에 바로 skip하는것을 허용한다.

각 리소스의 타입은 index entry의 하위 32-bit의 상위 8bit에 encode되어야한다. 현재 다음의 값이 resource type으로 정의됨

- 0x01 = UTF 8 string
- 0x10 = binary data
- 0x00 = end of resources

resource type은 ResourceManager 클래스에서 getResource와 getString method로 사용된다. 리소스의 타입의 차이는 resource 파일 내에서 arbitary order로 발생, 0x00의 타입을 제외함 (이것은 실제 리소스가아님)
. 파일에는 0x00타입의 entry는 하나여야하고 이것은 offset table의 마지막 entry여야한다. entry와 관련된 resource ID는 0x80000000이어야한다.

resource file의 최대 크기는 파일에서 resource의 갯수, 각 size와 offset으로 결정된다. 리소스 파일은 항상 최소한개의 offset의 헤더와 마지막 signatgure를 포함하고,
오직 한개일수도 있다. 그러므로 resource파일의 최소 사이즈는 4+4+8 = 16byte이다. 잘못된 리소스 파일이 사용되면 ResourceException을 DATA_ERROR 에러코드로 던져야한다.

리소스 파일에서의 octet이상의 단위를 가진 모든 data는 "Big Endian" 포맷으로 나타나야한다. (Network byte order)

- Sample resource file

  이 section은 sample binary resource file을 설명한다. 이 파일은 5개 resource를 포함한다. (3개의 string과 2개의 이미지).
파일의 hexadecimal dump는 file의 시작부터 offset label과 함께 argument된다. comment는 #과 함께 삽입된다. 이 offset label과 comment는 실제 파일의것이
아니고, 또한 image data도 보이지 않음.

000000 EE 4D 49 10 # signature and version
000004 00 00 00 30 # length of header
# start of offset table
# ID=0x00000040, type=0x01, offset 0x000038
000008 00 00 00 40 01 00 00 38
# ID=0x00000041, type=0x01, offset 0x00003A
8
A sample resource file Resources
000010 00 00 00 41 01 00 00 3A
# ID=0x00008000, type=0x10, offset 0x000040
000018 00 00 80 00 10 00 00 40
# ID=0x00008001, type=0x01, offset 0x00011F
000020 00 00 80 01 01 00 01 1F
# ID=0x00008002, type=0x10, offset 0x000123
000028 00 00 80 02 10 00 01 23
# ID=0x80000000, type=0x00 (end of resources), end offset
000030 80 00 00 00 00 00 02 20
# start of resources
# the string 'OK' (ID=0x0040)
000038 4F 4B
# the string 'Cancel' (ID=0x0041)
00003A 43 61 6E 63 65 6C
# data for image 'stop.png' (ID=0x8000)
000040 89 50 4E 47 0D 0A 1A 0A...
# the string 'Back' (ID=0x8001)
00011F 42 61 63 6B
# data for image 'ok.png' (ID=0x8002)
000123 89 50 4E 47 0D 0A 1A 0A...
000220 # end of file

sample resource파일은 리소스 id 40, 41, 8000, 8001, 8002를 가짐. 실행시에 파일의 컨텐츠에 접근하기위해서 ResourceManager가 instance가 생성된다.
getString을 호출하여 OK 스트링을 리턴할수 이고, getData를 호출하여 stop.png이미지 파일을 byte array로 부를수 있다. ResourceManager class doc은
API call에 대한 detail을 참조.

application 개발자는 application resource에 대해서 symbolic constant를 정의해야한다.

- Advantages of the binary format

PropertyResourceBundle class (J2SE) 에서 사용되는 tesxt-based format에 대해서 binary resource format이 가지는 장점에 대해서 설명한다.

. UTF-8의 사용은 programmer가 모든 텍스트에대해서 single character encoding을 사용하게 해준다. text의 language에 관계없이. J2SE PropertyResourceBundle
에서 모든 스트링은 ISO Latin-1 encoding이어야 하고, 모든 encoding밖의 문자는 \Uxxxx notation으로 정의되어야한다. Chinsese나 Japanese 문자에서 UTF-8
사용은 native encoding보다 더 많은 메모리를 사용하지만 \Uxxxx escape를 사용할 필요는 없다.

. Integers는 resource를 스트링으로 사용하는것보다 메모리를 적게먹는다. 이것은 ResourceManager API에서 사용되는 Resource ID에 직접 대응된다.

. binary format은 text-based format보다 storage를 적게쓰고, 효율적인 방법으로 읽을수 있다. mobile device에서는 두가지 고려사항은 중요함.

. binary format string은 newline을 포함할수 있다, line-delimited text file format과 달리.