Flutter & Dart

[Flutter] 다국어 지원

코딩하는후운 2022. 10. 22. 19:15
반응형

Flutter - 다국어 지원

https://software-creator.tistory.com/24

intl 패키지와 툴 써서 번역하기

플러터 다국어 지원은 좀 까다롭습니다.
Intl.message를 .arb파일로 바꾼 뒤 읽어들여야 한다.

.arb파일이란?
arb(Application Resource Bundle)는 구글에서 만든, 파일 형식입니다.
언어 데이터를 저장했다가 번역하기 위해 쓰이죠. 단순한 형태의 json파일이라고 보면됩니다.
플러터에선 arb말곤 다국어지원을 안해서, 어쨋든 arb파일 다루는 법을 알아야 합니다.

Google Translators Toolkit도 .arb파일형식을 지원하고 있습니다.


intl란?
intl은 다트에서 다국어(internalization and location)을 지원하는 패키지 입니다.
언어 번역이나 다수/복수, 성별, 날짜/숫자를 그 지역이나 국가에 맞게 바꿀 때 씁니다.

1.intl.message
일단 패키지들을 설치하고 설명을 따라해보세요.

1.1 pubspec.yaml설정
intl패키지와 intl_translation패키지를 추가해주세요

intl: ^0.15.8

1.2 intl.message()사용해보기
Message는 번역할 문자들을 말합니다. 이 문자들을 필요할 때, 한번에 추출해 번역합니다.
intl.message()은 문자를 담은 함수로 볼 수 있습니다.

import 'package:intl/intl.dart';

String helloWorld() => Intl.message(
  "Hello world",
  name: "helloWorld", //함수랑 동일
  args: [],
  desc: "Hello world message"
);

String openButton() => Intl.message(
  "open button",
  name: 'openButton',
  arts: [],
  desc: "this is an open button"
);

void main(){
  print(helloWorld());
  print(openButton());
}



Intl.message의 name은 꼭 함수이름과 일치해야 나중에 .arb파일로 추출할 수 있습니다.

1.3 Flutter에서 Intl.message사용해보기
위젯 코드는 보통때처럼 main.dart에 작성하고
Intl.message는 i18n/messages 클래스에 작성하겠습니다.

final msg = Messages();
사용: msg.widgetMessage, msg.appName


==i18n/messages.dart파일
import 'package:intl/intl.dart'

class Messages{
  String get widgetMessage => Intl.message(
    "widget message",
    name: "widgetMessage"
  );

  String get appName => Intl.message(
    "widget message",
    name: "appName"
  );
}




2.다국어 적용
1)intl message를 .arb로 추출하기
2)arb로 파일들 번역하기
3)arb를 message_xx.dart로 바꿔주기
4)app에 적용하기

2-1.intl의 message를 추출해 arb파일 만들기
intl_translation 패키지는 arb를 만드는 명령어를 지원합니다.

flutter pub run intl_translation:extract_to_arb --output-dir=[저장될 경로][arb를 추출할 dart파일]
같은 형식인데요. 경로와 파일을 정해줘야합니다.

파일에 있는 intl.message()만 골라서 arb로 바꿔주는 명령이다.
flutter pub run intl_translation:extract_to_arb --output-dir=lib/i18n lib/i18n/messages.dart
실행하면 intl_messages.arb이 생깁니다.

intl_messages.arb를 열어볼께요.

{
  "@@last_modified": "2019-07-02T08:43:15.261695",
  "widgetMessage": "widget message",
  "@widgetMessage": {
    "type": "text",
    "placeholders": {}
  },
  "appName": "widget message",
  "@appName": {
    "type": "text",
    "placeholders": {}
  }
}


messages.dart에 정의했던 intl.message()들이 json 형태로 바뀌어 있습니다.


2.2 arb로 파일들 번역하기
이제 Intl_messages.arb을 복사해 언어별 파일을 만듭니다.
intl_en.arb
intl_ko.arb

만든 arb을 언어에 맞게 수정해주면 된다.

arb파일을 직접 사용하진 못하고, 플러터에서 쓸 수 있게 dart 파일로 바꿔줘야 한다.
arb로부터 변환된 dart파일은 message_en.dart, message_kr.dart형식이 됩니다.


2.3 arb파일을 dart로 바꾸기
arb파일을 변환하려면 역시 intl_translation에서 지원하는 명령어를 써야합니다.

flutter pub run intl_translation:generate_from_arb --output-dir=[저장될 경로] --no-use-deferred-loading[문자열 있는 다트파일][번역된 arb파일들]

(맥,리눅스의 경우)
flutter pub run intl_translation:generate_from_arb --output-dir=lib/i18n --no-use-deferred-loading lib/i18n/messages.dart lib/i18n/intl_*.arb

(윈도우의 경우)
flutter pub run intl_translation:generate_from_arb --output-dir=lib/i18n --no-use-deferred-loading lib/i18n/messages.dart lib/i18n/intl_ko.arb lib/i18n/intl_en.arb
위 명령을 실행하면 messages_all.dart, messages_ko.dart, message_en.dart 가 만들어집니다.


2.4 app에 적용하기
다국어 적용은 LocationDelegate클래스를 써서 합니다.
번역된 message들을 읽어들이고, 어떤 언어를 지원하는지 알아내서 적용하죠.

i18n/app_localizations.dart

class AppLocalizations{
  static Future<AppLocalizations> load(Locale locale){
    final String name = locale.countryCode == null ? locale.languageCode : locale.toString();
    final String localName = Intl.canonicalizedLocale(name);

    return initializeMessages(localeName).then((bool _){
      Intl.defaultLocale = localeName;
      return new AppLocalizations();
    });
  }

  static AppLocalizations of(BuildContext context){
    return Localizations.of<AppLocalizations>(context, AppLocalizations);
  }
}

class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations>{
  @override
  bool isSupported(Locale locale){
    return ['en', 'ko'].contains(locale.languageCode);
  }

  @override
  Future<AppLocalizations> load(Locale locale){
    return AppLocalizations.load(locale);
  }

  @override
  bool shouldReload(LocalizationsDelegate<AppLocalizations> old){
    return false
  }
}




실제 적용

class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context){
    return MaterialApp(
      title: 'Flutter Demo',
      localizationsDelegates: [
        AppLocalizationDelegate(),
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: [Locale("en"), Locale("ko")],
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'flutter demo home page'),
    );
  }
}





3.IOS경우
info.plist도 업데이트 해줘야 합니다.
번역하려는 locale을 추가해야합니다.
info.plist
<key>CFBundleLocalizations</key>
<array>
  <string>en</string>
  <string>ko</string>
</array>

반응형