본문 바로가기
프로그래밍/Flutter 앱 개발

Flutter 앱 개발 8 : 다국어 지원 I

by drogrammer 2021. 1. 5.
반응형

코드가 더 복잡해 지기 전에 다국어 지원을 위한 구현을 추가해보자. 늦으면 늦을 수록 귀찮아 진다. ㅎ;

1. Easy Localization 패키지 추가

다국어 지원을 쉽게 도와주는 easy localization 패키지를 사용할 계획이니 pubspec.yaml 에 의존성을 추가하자.

...

dependencies:
  flutter:
    sdk: flutter
  url_launcher: ^5.7.10
  easy_localization: ^2.3.3 # 다국어 패키지 추가

...

 

2. 다국어 리소스 추가

assets 아래에 translations 폴더를 생성하고 언어별 리소스를 추가한다.

영어 (en.json), 스페인어 (es.json), 일본어 (ja.json), 한국어 (ko.json), 중국어 (zh.json) 를 추가했다.

다국어 리소스 파일 추가

 

앱에 사용된 문자열은 제목인 '오늘 우주는' 과 '앱 평가하기' 이므로 각각 'title', 'rate' 라는 이름으로 언어별 리소스를 작성하자.

한국어: ko.json

{
    "title": "오늘 우주는",
    "rate": "앱 평가하기"
}
영어: en.json

{
    "title": "Space Daily",
    "rate": "Rate this app"
}
스페인어: es.json

{
    "title": "El Universo Hoy",
    "rate": "Califica esta aplicación"
}
일본어: ja.json

{
    "title": "今日の宇宙",
    "rate": "アプリを評価"
}
중국어: zh.json

{

    "title": "今天的宇宙",
    "rate": "评价我们"
}

그리고 pubspec.yaml 의 flutter > assets 속성으로 리소스 폴더를 등록한다.

...

flutter:
  uses-material-design: true

  fonts:
    - family: NexonLv2GothicLight
      fonts:
        - asset: assets/fonts/NEXON Lv2 Gothic Light.ttf
    - family: NexonLv2GothicMedium
      fonts:
        - asset: assets/fonts/NEXON Lv2 Gothic Medium.ttf

  assets:
    - assets/translations/ # 다국어 리소스 폴더 추가

3. 다국어 지원 초기화

3.1. 기존 MaterialApp 을 Stateless 위젯으로 변경

기존에 runApp 에 넘기던 MaterialApp을 Stateless 위젯으로 일단 변경하고, 로케일 관련 설정을 build context로 부터 받아와서 설정한다. Stateless 위젯에 대한 설명은 아래 포스트를 참고하기 바란다.

 

Flutter 커스텀 위젯 (Stateless, Stateful)

기본적으로 플러터 UI 는 ListView, Column, Text 등 기본 위젯을 이용해서 구성한다. 하지만, 어플리케이션의 구현이 복잡해 질수록 재사용 가능한 커스텀 위젯의 개발이 불가피하다. 이번 포스트에서

drogrammer.tistory.com

lib/main.dart 를 아래와 같이 변경한다.

변경 전

import 'package:apod/view/contents.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    title: '오늘 우주는',
    theme: ThemeData(
      visualDensity: VisualDensity.adaptivePlatformDensity,
      primaryColor: Colors.black,
      fontFamily: 'NexonLv2GothicLight',
      scaffoldBackgroundColor: Colors.black,   // Scaffold 배경 색상 변경
      appBarTheme: AppBarTheme(
        centerTitle: true,                     // AppBar 의 타이틀을 중앙 정렬
      ),
    ),
    home: Contents(),
  ));
}

 

변경 후

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '오늘 우주는',
      // 로케일 delegate
      localizationsDelegates: context.localizationDelegates,
      // 지원하는 로케일
      supportedLocales: context.supportedLocales,
      // 설정된 로케일
      locale: context.locale,
      theme: ThemeData(
        visualDensity: VisualDensity.adaptivePlatformDensity,
        primaryColor: Colors.black,
        fontFamily: 'NexonLv2GothicLight',
        scaffoldBackgroundColor: Colors.black,
        appBarTheme: AppBarTheme(
          centerTitle: true,
        ),
      ),
      home: Contents(),
    );
  }
}

 

3.1. EasyLocalization 초기화

lib/main.dart 파일의 runApp 함수에 MyApp 을 바로 넘기는 대신, EasyLocalization 위젯으로 한번 감싸고 넘기면 다국어 지원 초기화가 된다. EasyLocalizatoin 사용시 활용한 옵션은 아래와 같다.

  • supportedLocales : 지원 로케일
  • path : 다국어 리소스 위치
  • fallbackLocale : 기본 로케일
  • child : 루트 위젯. 기존의 MaterialApp 을 넘기면 된다.
import 'package:apod/view/contents.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(
    // 다국어 지원 위젯
    EasyLocalization(
      // 지원 언어
      supportedLocales: [
        Locale('en'),
        Locale('es'),
        Locale('ko'),
        Locale('zh'),
        Locale('ja'),
      ],
      // 다국어 리소스 위치
      path: 'assets/translations',
      // 기본 로케일을 영어로 설정
      fallbackLocale: Locale('en'),
      // 루트 UI 위젯. 기존의 MyApp으로 설정
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '오늘 우주는',
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.locale,
      theme: ThemeData(
        visualDensity: VisualDensity.adaptivePlatformDensity,
        primaryColor: Colors.black,
        fontFamily: 'NexonLv2GothicLight',
        scaffoldBackgroundColor: Colors.black,
        appBarTheme: AppBarTheme(
          centerTitle: true,
        ),
      ),
      home: Contents(),
    );
  }
}

4. 다국어 적용

적용 방법은 간단하다. 적용 대상 리소스의 키에 tr() 이라는 함수를 호출하면 된다. 참고로 tr() 을 호출 하기 위해서는 아래 헤더를 추가해줘야 한다.

import 'package:easy_localization/easy_localization.dart';

변경할 문자열은 아래와 같다.

파일 위치 기존 문자열 변경
lib/main.dart '오늘 우주는' 'title'.tr()
lib/contents.dart '오늘 우주는' 'title'.tr()
lib/contents.dart '앱 평가하기' 'rate'.tr() 

변경한 코드는 아래와 같다.

lib/main.dart

import 'package:apod/view/contents.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(
    EasyLocalization(
      supportedLocales: [
        Locale('en'),
        Locale('es'),
        Locale('ko'),
        Locale('zh'),
        Locale('ja'),
      ],
      path: 'assets/translations',
      fallbackLocale: Locale('en'),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // 제목 다국어 지원
      title: 'title'.tr(),
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.locale,
      theme: ThemeData(
        visualDensity: VisualDensity.adaptivePlatformDensity,
        primaryColor: Colors.black,
        fontFamily: 'NexonLv2GothicLight',
        scaffoldBackgroundColor: Colors.black,
        appBarTheme: AppBarTheme(
          centerTitle: true,
        ),
      ),
      home: Contents(),
    );
  }
}

 

lib/contents.dart

import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:easy_localization/easy_localization.dart';

class Contents extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // 제목 다국어 지원
        title: Text('title'.tr()),
      ),
      drawer: Drawer(
        child: Container(
          color: Colors.grey[900],
          child: Column(
            children: [
              DrawerHeader(
                child: Center(
                  child: Text(
                    // Drawer 제목 다국어 지원
                    'title'.tr(),
                    style: TextStyle(color: Colors.white, fontSize: 30),
                  ),
                ),
                decoration: BoxDecoration(color: Colors.black),
              ),
              ListTile(
                leading: Icon(Icons.star, color: Colors.white),
                title: Text(
                  // 앱 평가하기 다국어 지원
                  'rate'.tr(),
                  style: TextStyle(color: Colors.white, fontSize: 20),
                ),
                onTap: () {
                  _launchURL(
                      "https://play.google.com/store/apps/details?id=com.contextract.apod");
                },
              ),
            ],
          ),
        ),
      ),
    );
  }

  void _launchURL(String url) async {
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      print('Could not launch $url');
    }
  }
}

 

5. 결과

시스템 언어 한국어 설정 시
시스템 언어 영어 설정 시

반응형

댓글