본문 바로가기

Flutter

[Flutter][Localizations]다국어 대응

728x90

 

 

1. pubspec.yaml

 

필요한 패키지들을 추가한다.

 

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations: # 다국어 패키지
    sdk: flutter
  intl: ^0.17.0 # 포맷 등의 패키지

 

flutter:
  # 자동 생성 유효화
  generate: true

=> .dart_tool/fluttergen/genl10n/applocalizations.dart 파일을 자동으로 생성하게 해준다.

 

 

generate 작성 위치

 

앱 실행 시, 이런 에러가 발생했다면 genearte 설정을 해주면 된다.

 

 

2. 다국어 지원 설정

 

import 'package:flutter_localizations/flutter_localizations.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Localization Ex',
      
      // 언어 설정에 따라 텍스트 및 리소스를 해당 언어로 동적으로 변경
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate
      ],
      
      // 지원하는 언어
      supportedLocales: [
        Locale('ko', ''),	// 한국어
        Locale('en', ''), 	// 영어
      ],
      home: MyHome(),
    );
  }
}

 

GlobalMaterialLocalizations : Material 디자인에 사용되는 텍스트 및 날짜 형식을 현지화 값으로 제공
GlobalWidgetsLocalizations : 텍스트 방향 처리, 몇몇의 언어는 글쓰기 방향이 다르기 때문에, LTR(Left-to-Right) 또는 RTL(Right-to-Left)을 고려하여 표시하게 한다.
GlobalCupertinoLocalizations : Cupertino 디자인을 사용하는 iOS 앱에서 특정 지역화된 문자열을 제공

 

 

3. l10n.yaml 파일 생성

l10n.yaml 파일은 코드를 generate 할 때 정보를 제공한다.

프로젝트 루트에 l10n.yaml 파일을 생성하고 아래 내용을 입력한다.

번역이 필요한 문자가 있다면, app_en.arb 파일을 기반으로 각 언어에 대한 arb 파일을 생성하고 그에 따라 app_localizations.dart 파일을 자동으로 생성하는데 사용된다.

 

# arb 파일이 저장된 디렉토리
arb-dir: lib/l10n

# arb 템플릿 정의 파일
template-arb-file: app_en.arb

# import 할 Dart 클래스 파일 정의
output-localization-file: app_localizations.dart

 

 

이제 위에서 설정한 경로에 맞게 arb 파일을 생성한다.

 

 

4. .arb(Application Resource Bundle) 파일 생성

Flutter에서 다국어 대응은 Intl.message를 .arb 파일로 바꾼 뒤 읽어야 한다.

 

Intl(Internationalization and localization)은 메시지 번역, 날짜/숫자 형식 등 현지화 기능을 제공하는 패키지다.

.arb란, 구글에서 만든 파일 형식이다.

Json 형태로, key 와 value로 이루어져 있다.

 

 

 

arb 파일에는 문자열 외에도 해당 문자열에 대한 메타데이터를 추가할 수 있다.

'@'는 메타데이터를 정의할 때 사용되는데, 해당 문자열에 대한 정보를 제공한다.

아래의 코드를 예시로 들면, "@helloWorld"는 "Hello World"라는 문자열에 대한 설명을 담고 있고, "@hello"는 "hello"에서 사용되는 변수인 '{name}'에 대한 설명과 예시를 제공한다. 이것은 개발자나 번역가가 적절한 번역을 생성하는데 도움이 된다.

 

 

app_en.arb

{
  "helloWorld" : "Hello World",
  "@helloWorld" : {
    "description" : "Programmer greeting"
  },

  "hello" : "Hello {name}",
  "@hello" : {
    "name" : {
      "description" : "userName",
      "example" : "John"
    }
  },

  "haveANiceDay" : "Have a nice day"
}

 

 

app_ko.arb

{
  "hello" : "안녕하세요 {name}",

  "haveANiceDay" : "좋은 하루 보내세요."
}

 

자동 생성된 dart 파일

 

 

4. 사용

 

AppLocalizations.delegate 코드 추가

 

 

MyApp.dart

import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';


class MyApp extends StatelessWidget {

        .. 기존 코드 ..
        
      localizationsDelegates: [
        AppLocalizations.delegate, // 코드 추가
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate
      ],

      .. 기존 코드 ..
    );
  }
}

 

 

필요한 문자열을 사용할 때는 아래와 같은 형태로 적어주면 된다.

 

AppLocalizations.of(context)!.helloWorld

 

 

MyHome.dart

import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class MyHome extends StatelessWidget {
  const MyHome({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          AppLocalizations.of(context)!.helloWorld
        ),
      ),
      body: Center(
        child: Text(
            AppLocalizations.of(context)!.hello('코린이')
        ),
      ),
    );
  }
}

 

 

 

(좌) 언어 설정 한국어 / (우) 언어 설정 영어

 

 

 

하지만 위의 방법들은 매번 context를 사용해야 하는 번거로움이 있다.

 

Flutter Intl 플러그인을 사용하면 그 불편함을 없앨 수 있다.

 

 

 


 

Flutter Intl 플러그인 사용하기

1. 플러그인 설치

처음에 .arb 파일을 생성할 때 뜨는 안내를 통해 들어가거나, Settings 메뉴를 통해 Flutter Intl 플러그인을 설치해주면 된다.

 

 

 

그리고 초기화해준다.

 

 

 

그럼 다음과 같은 파일들이 자동 생성된다.

 

 

intl_en.arb 파일을 복붙해서 intl_ko.arb 파일을 생성하면 messages_ko.dart 파일은 자동으로 생성된다.

 

 

2. 언어 파일 생성

각 arb 파일에 필요한 문자들을 작성한다.

 

intl_en.arb

{
  "test": "test!!!!!",
  "test2": "test2"
}

 

 

intl_ko.arb

{
  "test" : "테스트입니다!!!!!",
  "test2" : "두번째 테스트"
}

 

 

3. 사용

 

MyApp.dart

class MyApp extends StatelessWidget {
  const MyApp({super.key});

		.. 기존 코드 ..

      localizationsDelegates: [
        S.delegate, // 추가
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate
      ],

      supportedLocales: [
        Locale('en', ''),
        Locale('ko', ''),
      ],
    );
  }
}

 

 

MyHomePage.dart

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          Intl.message('test')
        ),
      ),

      body: Center(
        child: Text(
          Intl.message('test2')
        ),
      ),
    );
  }
}

 

(좌) 언어 설정 한국어 / (우) 언어 설정 영어

 

 

만약 첫번째 테스트처럼 변수로 name을 넣고 싶다면?

 

intl_en.arb

{
  "test": "test ^^",

  "test2" : "Hiiii. I'm {name}",
  "@test2" : {
    "description": "Greeting message",
    "placeholders": {
      "name": {
        "description": "User's name",
        "example": "John"
      }
    }
  }
}

 

 

intl_ko.arb

{
  "test": "테스트 ^^",

  "test2" : "안녕!!. 나는 {name}(이)야",
  "@test2" : {
    "description": "Greeting message",
    "placeholders": {
      "name": {
        "description": "User's name",
        "example": "John"
      }
    }
  }
}

 

 

MyHomePage.dart

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  @override
  Widget build(BuildContext context) {

    // 첫번째 방법
    String hello(String yourName) => Intl.message(
      'Hello, $yourName',
      name: 'test2',
      args: [yourName],
      desc: 'Say hello',
      examples: const {'yourName': 'James'},
    );

    return Scaffold(
      appBar: AppBar(
        title: Text(
          Intl.message('test')
        ),
      ),

      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(hello('James')),

            const SizedBox(height: 30,),

            // 두번째 방법
            Text(
              Intl.message('test2', args: ['코린이'])
            ),
          ],
        ),
      ),
    );
  }
}

 

 

(좌) 언어 설정 한국어 / (우) 언어 설정 영어

 

 

 

 

[참고]

https://jay-flow.medium.com/flutter-localizations-%EC%99%84%EC%A0%84-%EC%A0%95%EB%B3%B5-%ED%95%98%EA%B8%B0-8fa5f50a3fd2

 

[Flutter] Localizations 완전 정복 하기

Flutter에서 Localization(현지화)를 하는 방법은 수 없이 많다.

jay-flow.medium.com

 

https://fronquarry.tistory.com/8

 

플러터(Flutter) 다국어 대응하기 (Localization)

플러터 앱에서 환경별 언어 설정에 대응하기 위한 다국어 대응 i10n에 대해 알아보겠습니다. 다국어 대응 전 세계 스마트폰 시장에 앱을 출시한다면 한국 시장에 비해 규모가 커지고 수익도 늘어

fronquarry.tistory.com

 

https://api.flutter.dev/flutter/intl/Intl/message.html

 

message method - Intl class - intl library - Dart API

message static method String message(String messageText, {String? desc = '', Map ? examples, String? locale, String? name, List ? args, String? meaning, bool? skip} ) Use this for a message that will be translated for different locales. The expected usage

api.flutter.dev

 

 

 

728x90