
Chào các "Dev gen Z" tương lai, hôm nay, anh Creyt sẽ "khai sáng" cho các em một "siêu năng lực" mà bất kỳ ứng dụng nào muốn "vươn tầm thế giới" cũng cần phải có: khả năng "nói" nhiều thứ tiếng! Và "siêu năng lực" đó mang tên flutter_intl package.
1. flutter_intl là "thứ gì" mà "ghê gớm" vậy? Để làm gì?
Thử tưởng tượng thế này nhé: App của em giống như một "thần tượng K-Pop" vậy. Nếu "thần tượng" đó chỉ hát tiếng Hàn, họ sẽ chỉ "ăn điểm" với fan Hàn Quốc thôi đúng không? Nhưng nếu họ có thể hát tiếng Anh, tiếng Nhật, tiếng Trung, thậm chí là tiếng Việt, thì "độ phủ sóng" sẽ "khủng khiếp" đến mức nào? Fan từ khắp nơi trên thế giới sẽ "đổ rầm rầm" cho mà xem!
flutter_intl chính là "cái lò luyện" giúp app của em "đa ngôn ngữ", "đa văn hóa" như vậy đấy. Nó không chỉ giúp app "nói" được nhiều thứ tiếng (tiếng Anh, tiếng Việt, tiếng Tây Ban Nha...), mà còn giúp nó "hiểu" được "phong tục tập quán" của từng vùng miền nữa.
- Nói nhiều thứ tiếng (Localization - l10n): Giúp app hiển thị văn bản, nút bấm, thông báo bằng ngôn ngữ mà người dùng quen thuộc. Tưởng tượng người dùng Pháp mở app của em lên mà thấy toàn tiếng Việt, họ "tụt mood" ngay đúng không?
flutter_intlsẽ giúp app "tự động" chuyển sang tiếng Pháp cho họ. - Hiểu "phong tục tập quán" (Internationalization - i18n): Không chỉ là dịch từ ngữ,
flutter_intlcòn giúp app "thông minh" hơn trong việc hiển thị ngày tháng (ở Mỹ là MM/DD/YYYY, ở Việt Nam là DD/MM/YYYY), số liệu (dùng dấu phẩy hay dấu chấm để phân cách phần thập phân), tiền tệ (USD, VNĐ, EUR), v.v. Điều này cực kỳ quan trọng để app của em "thân thiện" và "chuyên nghiệp" trong mắt người dùng toàn cầu.
Nói tóm lại, flutter_intl giúp app của em "ghi điểm" với người dùng từ mọi miền "thiên hạ", tăng trải nghiệm người dùng (UX) và mở rộng "thị trường" của app.
2. Code Ví Dụ Minh Họa: "Thực chiến" thôi!
Để bắt đầu, chúng ta cần "nhúng" flutter_intl vào dự án của mình. Anh sẽ hướng dẫn từng bước "chuẩn không cần chỉnh" nhé.
Bước 1: Cấu hình pubspec.yaml
Thêm các dependencies sau vào file pubspec.yaml của em:
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: any # Hoặc phiên bản cụ thể như ^0.18.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
intl_utils: ^2.8.5 # Package này giúp tự động tạo code từ file .arb
flutter:
uses-material-design: true
generate: true # RẤT QUAN TRỌNG: Bật tự động tạo code cho localization
Sau khi thêm, chạy flutter pub get nhé.
Bước 2: Tạo file cấu hình l10n.yaml
Ở thư mục gốc của dự án (ngang hàng với pubspec.yaml), tạo file l10n.yaml với nội dung sau:
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
arb-dir: Nơi chứa các file dịch.arbcủa em.template-arb-file: File.arbmặc định dùng làm template.output-localization-file: Tên file Dart sẽ được tự động tạo.
Bước 3: Tạo các file .arb (Application Resource Bundle)
Trong thư mục lib, tạo thư mục l10n. Bên trong l10n, tạo các file sau:
lib/l10n/app_en.arb (Tiếng Anh - ngôn ngữ mặc định)
{
"appName": "My Awesome App",
"helloWorld": "Hello World!",
"greeting": "Hello {name}, welcome to your app!",
"@greeting": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"numberOfMessages": "{count, plural, =0{No messages} =1{One message} other{{count} messages}}",
"@numberOfMessages": {
"placeholders": {
"count": {
"type": "int"
}
}
}
}
lib/l10n/app_vi.arb (Tiếng Việt)
{
"appName": "Ứng Dụng Tuyệt Vời Của Tôi",
"helloWorld": "Xin Chào Thế Giới!",
"greeting": "Chào {name}, chào mừng bạn đến với ứng dụng của bạn!",
"numberOfMessages": "{count, plural, =0{Không có tin nhắn} =1{Một tin nhắn} other{{count} tin nhắn}}"
}
Bước 4: Chạy lệnh để tạo code
Sau khi có các file .arb và cấu hình, chạy lệnh sau trong terminal của dự án:
flutter gen-l10n
Hoặc nếu dùng intl_utils:
flutter pub run intl_utils:generate
Lệnh này sẽ tự động tạo ra file app_localizations.dart (và các file hỗ trợ khác) trong thư mục lib/l10n. Đây là file mà chúng ta sẽ dùng để truy cập các chuỗi dịch.
Bước 5: Cấu hình MaterialApp
Trong file main.dart, cấu hình MaterialApp để nó "hiểu" về các ngôn ngữ mà app hỗ trợ.
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; // Import file tự động tạo
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Localization Demo',
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [
Locale('en', ''), // Tiếng Anh
Locale('vi', ''), // Tiếng Việt
],
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _messageCount = 0;
void _incrementMessageCount() {
setState(() {
_messageCount++;
});
}
@override
Widget build(BuildContext context) {
// Cách truy cập các chuỗi dịch
final l10n = AppLocalizations.of(context)!;
return Scaffold(
appBar: AppBar(
title: Text(l10n.appName), // Sử dụng chuỗi dịch cho tiêu đề app
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(l10n.helloWorld), // Sử dụng chuỗi dịch
const SizedBox(height: 20),
Text(
l10n.greeting('Creyt'), // Truyền tham số vào chuỗi dịch
style: Theme.of(context).textTheme.headlineMedium,
),
const SizedBox(height: 20),
Text(
l10n.numberOfMessages(_messageCount), // Xử lý số nhiều
style: Theme.of(context).textTheme.headlineSmall,
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _incrementMessageCount,
child: const Text('Add Message'),
),
],
),
),
);
}
}
Sau khi chạy app, em có thể thay đổi ngôn ngữ của điện thoại hoặc trình giả lập để xem app tự động chuyển đổi ngôn ngữ như thế nào nhé!

3. Mẹo "hack não" (Best Practices) từ "lão làng" Creyt
-
Ghi nhớ "thần chú" i18n vs l10n:
- i18n (Internationalization - Quốc tế hóa): Là việc "chuẩn bị" cho app của em sẵn sàng để hỗ trợ nhiều ngôn ngữ. Giống như việc em mua một cái vali to để chuẩn bị đi du lịch nhiều nước vậy. Nó là cấu trúc, là framework.
- l10n (Localization - Bản địa hóa): Là việc "đổ dữ liệu" vào cái vali đó, tức là dịch các chuỗi văn bản, điều chỉnh định dạng ngày giờ, tiền tệ cho từng vùng cụ thể. Giống như em bỏ quần áo mùa đông khi đi Bắc Âu, đồ bơi khi đi biển vậy. Nó là nội dung.
- Mẹo nhớ: i18n (có 18 chữ cái giữa i và n), l10n (có 10 chữ cái giữa l và n).
-
Luôn có một ngôn ngữ mặc định (Fallback Locale): Đảm bảo app của em luôn có một ngôn ngữ để hiển thị, phòng trường hợp không tìm thấy bản dịch cho ngôn ngữ hiện tại của người dùng. Thường là tiếng Anh.
-
Dùng Placeholder "ngon lành": Khi cần chèn biến vào chuỗi dịch (như
Hello {name}), hãy khai báo@greetingvớiplaceholderstrong file.arbđểintlbiết kiểu dữ liệu và generate code chuẩn xác. -
Cẩn thận với độ dài chuỗi: Một câu tiếng Anh ngắn gọn có thể trở nên dài "lê thê" trong tiếng Đức hoặc tiếng Việt. Hãy kiểm tra giao diện người dùng trên nhiều ngôn ngữ để tránh bị "vỡ layout" nhé.
-
Sử dụng công cụ hỗ trợ: Có nhiều extension trong VS Code hoặc IntelliJ IDEA giúp quản lý các file
.arbdễ dàng hơn, ví dụ như "ARB Editor" hoặc "Flutter Intl". Chúng giúp highlight cú pháp, kiểm tra lỗi và đồng bộ các khóa dịch.
4. Ứng dụng thực tế: "Ai đang dùng cái này?"
Thực ra, hầu hết các ứng dụng "xịn sò" mà em dùng hàng ngày đều có "siêu năng lực" này đấy!
- Netflix, Spotify, Facebook, Google Maps: Các ông lớn này đều phục vụ hàng tỷ người dùng trên khắp thế giới. Không có đa ngôn ngữ, họ sẽ mất đi một lượng lớn "khách hàng tiềm năng".
- Các ứng dụng ngân hàng, thương mại điện tử: Những app này không chỉ dịch ngôn ngữ mà còn phải cực kỳ chính xác trong việc hiển thị tiền tệ, ngày giao dịch theo từng quốc gia để tránh nhầm lẫn và tăng độ tin cậy.
- Game mobile: Đồ họa đẹp mấy mà ngôn ngữ khó hiểu thì cũng "toang". Các game thường hỗ trợ rất nhiều ngôn ngữ để "chiều lòng" game thủ toàn cầu.
5. "Anh Creyt" đã từng "thử nghiệm" và "khuyên dùng" cho case nào?
Anh Creyt đã "chinh chiến" qua nhiều dự án Flutter, và đây là "đúc kết xương máu":
-
Nên dùng ngay từ đầu nếu: App của em có "tham vọng" vươn ra khỏi biên giới Việt Nam, hoặc thậm chí chỉ là phục vụ người dùng Việt Nam nhưng muốn có cả tiếng Anh (ví dụ: cho người nước ngoài đang sống ở Việt Nam). Việc tích hợp
flutter_intltừ sớm sẽ giúp em tiết kiệm "cả tấn" thời gian và công sức sau này. Chứ để đến lúc app "phình to" rồi mới lo dịch thì đúng là "cực hình", cảm giác như phải "nhổ từng sợi tóc" vậy. -
Khi nào có thể "tạm hoãn" (nhưng vẫn khuyến khích làm quen): Nếu app của em cực kỳ nhỏ, chỉ là một ứng dụng cá nhân, không có ý định chia sẻ rộng rãi, và chỉ có vài dòng chữ cố định. Tuy nhiên, anh vẫn khuyên các em nên làm quen với
intlngay cả trong những dự án nhỏ để "tập tành", "luyện tay nghề". Vì biết đâu, một ngày nào đó cái app nhỏ xíu đó lại "hot" và em muốn "scale" nó lên thì sao?
Kinh nghiệm xương máu của anh: Đừng bao giờ "lười" mà hardcode (viết thẳng) các chuỗi văn bản vào code nếu em có ý định làm app đa ngôn ngữ. Nó giống như việc em "tự đào hố chôn mình" vậy. Sau này muốn dịch, em phải dò từng file, từng dòng code để tìm và sửa. Cực kỳ tốn thời gian và dễ gây lỗi. flutter_intl là "vị cứu tinh" giúp em quản lý tất cả các chuỗi dịch ở một nơi duy nhất, dễ dàng bảo trì và mở rộng.
Hy vọng bài giảng này đã giúp các em "thông não" về flutter_intl và tầm quan trọng của nó. Hãy "thực hành ngay" để biến app của mình thành "công dân toàn cầu" nhé! Bất cứ thắc mắc gì, cứ "bắn" câu hỏi cho anh Creyt!
Thuộc Series: Flutter
Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!