일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- entity
- 0.25px border
- 0.75px border
- Websocket
- npm
- 10px
- 으
- 0.5px border
- ZOOM
- &연산
- TS
- jwt
- 문서번호
- 당근마켓
- literal
- 1px border
- Props
- angular
- TypeScript
- 타입스크립트
- es6
- 컴포넌튼
- 전역변수
- 데이터베이스 #try #이중
- ES5
- font-size
- 클론코딩
- github
- Strict
- 서버리스 #
- Today
- Total
복잡한뇌구조마냥
[Angular] Text Management/Translation (Text 관리 및 번역) 본문
❗️Problem
- Angular에서 Text를 관리하는 방법
- 일반적으로 사용하는 Text관리 방법은 무엇인가?
- LiveStudio 내에서 사용하는 모든 Text를 일괄적으로 관리하는 방법이 필요하다.
- Text들을 Translation하는 방법
- Angular에서 지원하는 traslation은 무엇이고, 어떤 라이브러리들이 있는가?
- LiveStudio에 적용하기에 가장 효과적인 방법은 무엇인가?
⚠️ Text 관리방법
⭐️ 일반적 Text 관리 방법
1. String을 이용한 Text 관리
공식 문서 :
const string1 = "A string primitive";
const string2 = 'Also a string primitive';
const string3 = `Yet another string primitive`;
const string4 = new String("A String object");
2. Service를 활용한 Text 관리
- Service에 text 객체를 만들어 함수를 통해 매칭되는 text를 교체하는 방식
3. Server를 활용한 Text 관리
- 서버에서 언어별 리소스 교체
⭐️ File을 이용한 Text 관리
공식 문서 : Angular
ARB:
Flutter ARB file (.arb) - Localizely
XLIFF: https://en.wikipedia.org/wiki/XLIFF
XLIFF - Wikipedia
From Wikipedia, the free encyclopedia Computer file format XLIFF (XML Localization Interchange File Format) is an XML-based bitext format created to standardize the way localizable data are passed between and among tools during a localization process and a
en.wikipedia.org
XMB: https://filext.com/file-extension/XMB
⭐️ JSON을 이용한 Text 관리
공식 문서:
JSON으로 작업하기 - Web 개발 학습하기 | MDN
공식 문서:
Internationalization - Mozilla | MDN
예제 자료:
GitHub - workshopper/how-to-npm: A module to teach you how to module.
{
"squadName": "Super hero squad",
"homeTown": "Metro City",
"formed": 2016,
"secretBase": "Super tower",
"active": true,
"members": [
{
"name": "Molecule Man",
"age": 29,
"secretIdentity": "Dan Jukes",
"powers": ["Radiation resistance", "Turning tiny", "Radiation blast"]
},
{
"name": "Madame Uppercut",
"age": 39,
"secretIdentity": "Jane Wilson",
"powers": [
"Million tonne punch",
"Damage resistance",
"Superhuman reflexes"
]
},
{
"name": "Eternal Flame",
"age": 1000000,
"secretIdentity": "Unknown",
"powers": [
"Immortality",
"Heat Immunity",
"Inferno",
"Teleportation",
"Interdimensional travel"
]
}
]
}
⭐️Angular i18n(Internationalization)을 이용한 Text 관리
공식 문서 : Angular
예제 자료:
GitHub - StephenFluin/i18n-sample: A sample of internationalization with Angular 2 RC 6
- HTML의 Text가 필요한 각각의 태그에 i18n 속성을 @@접두사를 사용하여 정의
2./locale/messages.${locale}.xlf형식의 파일을 생성 - 언어마다 파일 생성
각 id의 요소로 i18n 태그에 매칭되는 값을 작성하여 번역되는 내용을 표시
3. 두 요소 모두 동일한 사용자 정의 ID로 정의되어있어 동일한 번역으로 동작
장점 : text를 변경해도 id를 변경하지 않기 때문에 번역을 업데이트 하기 위한 추가 단계를 수행할 필요 없음.
단점: 텍스트를 변경하면 새로 변경된 원본 텍스트와 동기화 되지 않을 수 있음.
( 첫번째 작성된 원본은 유지 해야함 - 위의 예제의 경우 최상단 Hello가 유지되야 동작함.)
⚠️ Translate 방법
i18n이란 (국제화, Internationalization)
참고 자료: https://www.freecodecamp.org/news/how-to-implement-localization-in-angular-using-i18n-tools-a88898b1a0d0/
참고 자료 : https://velog.io/@youngjjjjj/i18n%EA%B3%BC-l10n%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C
참고 자료: https://miaow-miaow.tistory.com/32
i18n 이 뭔가요? SW 국제화가 뭔가요? 현지화가 뭔가요?
목표: Internationalization (i18n) 파악하기 요약 i18n 은 Internationalization 의 축약형임 SW국제화란 국제적으로 통용되는 SW를 설계하고 개발하는 과정 SW현지화란 현지(Locale) IT 환경에 적합하도록 SW 를 개
miaow-miaow.tistory.com
I18n국제화라고도 하며, 앱이 전 세계 사용자에게 도달 범위를 확장하기 위해 다양한 언어를 지원하도록 만드는 프로세스입니다.
1. 소프트웨어의 국제화
- 언어별 번역
-> 국제화의 가장 큰 의미이다. - 문자 인코딩 설정
-> 초기에 문자를 표현하는 대표적인 방식은 ASCII 인코딩 방식이었으나, 한글이나 한자 같은 문자는 2개 이상의 특수 문자를 합쳐서 표현하곤 했는데, 이러한 방식은 비정상적이고 그에 따라 문자가 깨지거나 제대로 표현하지 못하여 2~4바이트 공간에 여유롭게 문자를 할당하고자 나온 방식이 Unicode이다. Unicode 자체는 1바이트로 표현이 가능한 영문자도 2바이트 이상의 공간을 사용하여 메모리 낭비가 심하여 이를 가변 길이 문자 인코딩 방식으로 나온 것이 UTF-8이다. - 문자열 치환 방법
1. Server Side (서버에서 언어별 리소스 교체)
2. Client Side (클라이언트에서 언어별 리소스 교체)- Client Side가 Server Side보다 많은 경우에서 좋은 방법이다. 왜냐하면 리소스 캐시와 선호 언어 설정 등이 가능하기 때문이다.
2. 디자인의 국제화
소스 코드의 변경 없이도 다양한 언어 / 지역을 지원할 수 있도록 처리해야한다.
왜냐하면 언어 / 지역별로 가독성이 적절해야하고, 번역으로 인해 문자열의 길이가 길어질 수 있기 때문이다. (ex 국제화 -> internationalization)
3. 리소스의 국제화
언어 / 지역에 맞춰 가장 적절한 리소스를 준비해야한다.
4. 고려할 사항 정리
요소
설명
목적
유니코드
|
세계의 모든 문자를 컴퓨터에서 일관되게 표현하고 다룰 수 있도록 설계된 산업 표준 | 각 언어와 문자 체계에 따른 충돌 문제 해결 |
리소스 외부화 및 관리
|
이미지, 바이너리 코드, 소스 코드 등으로부터 리소스를 분리(외부화)하는 것 | 프로그램의 수정 없이 다국어 지원이 가능하도록 하기 위함 |
Locale 대응
|
날짜/시간 형식, 달력, 통화 기호, 문자열 정렬 순서 등 | 국제화 라이브러리를 이용하여 다수의 Locale에 유연하게 대응하기 위함 |
Localizability
|
다국어로 번역될 경우 사용자 인터페이스에 미치는 영향을 분석하는 것 | UI가 구성한 의도에 맞게 언어별로 처리할 수 있는지 확인하기 바람 |
📚 l10n이란 (현지화, Localiztion)
l10n이란 특정 목표 시장(국가)의 문화 및 기타 요구 사항을 충족시키는 작업
1. LTR / RTL (쓰기 방향의 차이)
-> 일부 중동 국가에서는 표기방식을 오른쪽에서 왼쪽으로 읽음. 그에 따라 UI와 HTML 코드 수정이 필요해짐.
2. 숫자, 날짜 및 시간 형식
-> 나라마다 화폐(콤마), 날짜 표현 방식이 다 다름.
3. 문자열 정렬 방법
-> 나라마다 알파벳을 정렬하는 방법이 다름 (ex 발음의 강세가 표현된 글자) Collation 참고
4. 개인 이름 및 주소 형식 처리 등
-> 나라마다 개인 이름 및 주소 형식이 다름.
⭐️라이브러리
참고 문서: https://phrase.com/blog/posts/the-best-javascript-i18n-libraries/
참고 문서: https://crowdin.com/blog/2023/03/20/angular-localization-and-i18n
A Guide to Angular Localization and i18n — Crowdin
Learn how to use i18n in Angular and how to automate Angular localization, instead of copy-pasting text strings.
crowdin.com
i18next |
|
⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️⭐️ | 350만 | 56.3KB [14.8KB gzip] |
✅ 복합 복수형 ✅ 숫자 ✅ 날짜(+ 상대) ✅ TypeScript ✅ 메시지 추출 ✅ ICU 구문 |
메시지 추출 및 ICU 지원은 자사 추가 기능을 통한 선택 사항입니다. |
FormatJS |
|
⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️⭐️ | 120만 | 62.8KB [17.8KB gzip] |
✅ 복합 복수형 ✅ 숫자 ✅ 날짜(+ 상대) ✅ TypeScript ✅ 메시지 추출 ✅ ICU 구문 |
최고 수준의 ICU 메시지 구문 지원. |
vue-i18n | Vue (third-party) | ⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️ | 984K | 63.8KB [18.9KB gzip] |
🟡 복합 복수형 (참고 사항 참조) ✅ 숫자 ✅ 날짜 ✅ TypeScript ❌ 메시지 추출 ❌ ICU 구문 |
복잡한 복수형에 대한 고유한 논리를 제공해야 합니다. |
@angular/ localize |
Angular (first-party) | ⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️⭐️ | 766K | 4.6KB [1.9KB gzip] |
✅ 복합 복수형 ✅ 숫자 ✅ 날짜 ✅ TypeScript ✅ 메시지 추출 ✅ ICU 구문 |
|
Globalize | (See Notes) | ⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️ | 198K | 71.1kB [22.2kB gzip] (참고 참조) |
✅ 복합 복수형 ✅ 숫자 ✅ 날짜(+ 상대) ✅ TypeScript ❌ 메시지 추출 ✅ ICU 구문 |
|
Polyglot |
|
⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️ | 184K | 35.5kB [10.5kB gzip] |
✅ 복합 복수형 ❌ 숫자 ❌ 날짜 ❌ TypeScript ❌ 메시지 추출 ❌ ICU 구문 |
|
jQuery.i18n | jQuery (third-party) | ⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️ | 해당 없음 (참고 사항 참조) |
1.1kB [0.7kB gzip] (참고 사항 참조) |
✅ 복합 복수형 ❌ 숫자 ❌ 날짜 ❌ TypeScript ❌ 메시지 추출 ❌ ICU 구문 |
|
1. @angular/localize
공식 문서 : https://angular.io/api/localize
사용 방법 :
- ng build --localize CLI에 자동으로 Locale 데이터가 포함됨
- import '@angular/common/locales/global/ko'; 를 통해 필요한 곳에서 가져옴
-
const message = $localize`Hello, World!`;
<h1 i18n>Hello, World!</h1>
- $localize를 선언하여 단어를 i18n으로 번역하는 식으로도 사용 가능
장점 : angular 내부에 정해져서 나오는 값이 있음, 용량이 낮음
단점 : 지정하는 방식이 쉽지않음, 사용 예제가 많이 없음.
2. ngx-translate
공식 문서 : https://github.com/ngx-translate/core
참고 자료 : https://www.codeandweb.com/babeledit/tutorials/how-to-translate-your-angular-app-with-ngx-translate
참고 자료: https://gogomalibu.tistory.com/150
사용 방법
- 모듈 설치
> npm install @ngx-translate/core --save - > npm install @ngx-translate/http-loader --save
- app.module.ts 에 추가
- @NgModule({ declarations: [AppComponent, ... 이외에 사용하는 여러 컴포넌트들], imports: [ BrowserModule, ReactiveFormsModule, ... TranslateModule.forRoot({ useDefaultLang: true, defaultLanguage: 'ko', loader: { provide: TranslateLoader, useFactory: HttpLoaderFactory, deps: [HttpClient] } }) ], bootstrap: [AppComponent] }) export class AppModule { } export function HttpLoaderFactory(http: HttpClient) { return new TranslateHttpLoader(http, './assets/locale/', '.json'); }
- 언어 별 json 파일 생성
ex ) assets/i18n/ko.json - { "btn": { "create": "추가", "update": "수정", "save": "저장", "cancel": "취소", "delete": "삭제" }, "placeholder": { "search-menu": "메뉴 검색" } }
- component 에서 translate 사용하기
constructor(private translate: TranslateService) { ... } this.translate.get('btn.create').subscribe((res: string) => { console.log(res); });
- <li (click)="edit()">{{ 'btn.update' | translate }}</li>
3. i18next
공식 문서: https://www.i18next.com/
참고 자료 : https://phrase.com/blog/posts/angular-l10n-with-i18next/
참고 자료 : https://github.com/Romanchuk/angular-i18next
예제 자료: https://github.com/Romanchuk/angular-i18next-demo/tree/master
예제 자료: https://romanchuk.github.io/angular-i18next/
사용방법:
<div>{{ 'test' | i18next }}</div>
<div>{{ 'test' | i18next: { count: 5, nsSeparator: '#' } }}</div>
플러그인
import { I18NextModule, ITranslationService, I18NEXT_SERVICE } from 'angular-i18next';
// import Backend from 'i18next-xhr-backend'; //for i18next < 20.0.0
import HttpApi from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
...
i18next.use(HttpApi)
.use(LanguageDetector)
.init(i18nextOptions)
i18n 초기화
export function appInit(i18next: ITranslationService) {
return () => i18next.init();
}
export function localeIdFactory(i18next: ITranslationService) {
return i18next.language;
}
export const I18N_PROVIDERS = [
{
provide: APP_INITIALIZER,
useFactory: appInit,
deps: [I18NEXT_SERVICE],
multi: true
},
{
provide: LOCALE_ID,
deps: [I18NEXT_SERVICE],
useFactory: localeIdFactory
}];
라우팅 경로 변경으로 언어 설정
export class AppComponent implements OnInit {
constructor(private router: Router,
private title: Title,
@Inject(I18NEXT_SERVICE) private i18NextService: ITranslationService) {
// page title subscription
// https://toddmotto.com/dynamic-page-titles-angular-2-router-events#final-code
this.router.events
.filter(event => event instanceof NavigationEnd)
.map(() => this.router.routerState.root)
.map(route => {
while (route.firstChild) route = route.firstChild;
return route;
})
.filter(route => route.outlet === 'primary')
.mergeMap(route => route.data)
.subscribe((event) => this.updatePageTitle(event['title']));
}
ngOnInit() {
this.i18NextService.events.languageChanged.subscribe(lang => {
let root = this.router.routerState.root;
if (root != null && root.firstChild != null) {
let data: any = root.firstChild.data;
this.updatePageTitle(data && data.value && data.value.title);
}
});
}
updatePageTitle(title: string): void {
let newTitle = title || 'application_title';
this.title.setTitle(newTitle);
}
}
4. FormatJS
공식 문서: https://formatjs.io/
참고 자료: https://phrase.com/blog/posts/react-i18n-format-js/#how-do-i-localize-my-app-with-react-intl
사용 방법:
- 번역 파일
- // src/lang/en-US.json { "app.title": "Yomtaba", "app.tagline": "recipe of the day" } 코드 언어: JSON / 주석이 포함된 JSON ( json ) // src/lang/ar-EG.json { "app.title": "يومتابا", "app.tagline": "وصفة اليوم" }
- 컴포넌트에서 사용
- export default function Recipe(){ const intl = useIntl(); return ( <main> <h2> <FormattedMessage id="recipe..title" /> </h2> </main> ) }
5. jQuery.i18n
참고 자료: https://github.com/wikimedia/jquery.i18n
- 번역 파일
- { "@metadata": { "authors": [ "Alice", "David", "Santhosh" ], "last-updated": "2012-09-21", "locale": "en", "message-documentation": "qqq", "AnotherMetadata": "AnotherMedatadataValue" }, "en": { "appname-title": "Example Application", "appname-sub-title": "An example application with jquery.i18n", "appname-header-introduction": "Introduction", "appname-about": "About this application", "appname-footer": "Footer text" }, "ml": { "appname-title": "അപ്ലിക്കേഷന് ഉദാഹരണം", "appname-sub-title": "jquery.i18n ഉപയോഗിച്ചുള്ള അപ്ലിക്കേഷന് ഉദാഹരണം", "appname-header-introduction": "ആമുഖം", "appname-about": "ഈ അപ്ലിക്കേഷനെപ്പറ്റി", "appname-footer": "അടിക്കുറിപ്പു്" } }
- jquery로 호출 - 특정 단어 또는 파일로 참조 가능
- $.i18n().load( { en: { 'message-hello': 'Hello World', 'message-welcome': 'Welcome' }, hi: 'i18n/messages-hi.json', // Messages for Hindi de: 'i18n/messages-de.json' } );
6. angular-translate
공식 문서: https://angular-translate.github.io/
참고 자료: https://github.com/angular-translate/angular-translate
예제 자료: https://angular-translate.github.io/docs/#/guide/05_using-translate-directive
index.html
<body>
<div ng-controller="Ctrl">
<p>{{ 'HEADLINE' | translate }}</p>
<img src="mylogo.png" translate-attr="{ alt: 'LOGO' }"></img>
<p>{{ 'PARAGRAPH' | translate }}</p>
<p translate>PASSED_AS_TEXT</p>
<p translate="PASSED_AS_ATTRIBUTE"></p>
<p translate>{{ 'PASSED_AS_INTERPOLATION' }}</p>
<p translate="{{ 'PASSED_AS_INTERPOLATION' }}"></p>
</div>
</body>
script.js
var translations = {
HEADLINE: 'What an awesome module!',
PARAGRAPH: 'Srsly!',
LOGO: 'My cool logo',
PASSED_AS_TEXT: 'Hey there! I\'m passed as text value!',
PASSED_AS_ATTRIBUTE: 'I\'m passed as attribute value, cool ha?',
PASSED_AS_INTERPOLATION: 'Beginners! I\'m interpolated!'
};
var app = angular.module('myApp', ['pascalprecht.translate']);
app.config(['$translateProvider', function ($translateProvider) {
// add translation table
$translateProvider
.translations('en', translations)
.preferredLanguage('en');
}]);
app.controller('Ctrl', ['$scope', function ($scope) {
}]);
⭐️Angular에서 사용 가능한 Library
- @angular/localize
- 장점
- Angular에서 제공하는 내용을 사용할 수 있음
- 용량이 작음
- 단점
- 사용하기위한 연구가 필요함.
- 다른 라이브러리로 변경이 어려움 (JSON 형식이 아님)
- 사용 예제가 많이 없음
- 언어별로 프로젝트가 따로 빌드된다는 얘기가 있
- 장점
- I18next
- 장점
- JSON 형식
- 다수의 프레임 워크에서 사용하는 라이브러리임
- 지원하는 항목이 많음
- 다양한 옵션으로 커스터마이징 가능
- 단점
- Angular용 i18next는 i18next 자체 제작이 아님
- 대부분 예제는 리액트임
- Angular 최신용 버전이 아직 개발 단계임
- 언어 변경 시에 깜빡임 현상이 일어남
- 장점
- @ngx-translate
- 장점
- JSON 형식
- Angular 적용이 편함
- 그나마 최근에 업데이트가 되었음
- 언어 변경 시 깜빡임 없음
- 단점
- 최근 Angular 16용으로 구축됨
- 장점
- angular-translate
- 장점
- JSON 형식
- Angular 적용이 편함
- 언어 변경 시 깜빡임 없음
- 단점
- 적용하기 전에 사전작업이 필요
- 최신 업데이트가 없음
- 자료가 많이 없음
- 장점
✅결론
현재 LiveStudio에 적용에는 @ngx-translate 를 적용하는게 유리하다고 판단됨.
'FE > Angular' 카테고리의 다른 글
Angular XSS 공격 방어 (0) | 2025.04.15 |
---|---|
[Angular Material] Dialog Modal 자동 포커스 끄기 (0) | 2023.12.11 |
Angular 공부 ( XSS공격 방어 ) (0) | 2023.04.04 |
Angular 공부 ( 컴포넌트간 데이터 전송 [ Input, Output ] ) (0) | 2023.03.16 |
Angular 공부 ( real-time-chart ) (0) | 2023.01.26 |