GetX:多语言

入门案例

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

// ------------------------ 1.创建语言类 ------------------------------
class MyTranslations extends Translations {
  @override
  Map<String, Map<String, String>> get keys => {
    'en_US': {'hello': 'Hello', 'welcome': 'Welcome to GetX'},
    'zh_CN': {'hello': '你好', 'welcome': '欢迎使用 GetX'},
  };
}

// -------------------------- 2.在 GetMaterialApp 中注册 --------------------
void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'GetX i18n Demo',
      translations: MyTranslations(), // 注册翻译类
      locale: const Locale('zh', 'CN'), // 默认语言
      fallbackLocale: const Locale('en', 'US'), // 兜底语言
      home: const HomePage(),
    );
  }
}

// -------------------------- 3.在界面中使用 tr 获取翻译文本 --------------------------

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('hello'.tr)),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('welcome'.tr),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                // 切换语言
                if (Get.locale?.languageCode == 'zh') {
                  Get.updateLocale(const Locale('en', 'US'));
                } else {
                  Get.updateLocale(const Locale('zh', 'CN'));
                }
              },
              child: Text('切换语言 / Switch Language'),
            ),
          ],
        ),
      ),
    );
  }
}

一个静态文本映射系统

GetX 的多语言功能 并不是自动翻译(AI 翻译或 Google Translate 风格的实时翻译),它本质上是 一个静态文本映射系统,更像是 “关键位置的语言配置”。

它需要手动定义文本映射,为每个 key 写好各语言对应的翻译。

'login': '登录', // zh_CN
'login': 'Login', // en_US

适合按钮文字、提示信息、标题、标签等界面结构性文字。但是不适合动态内容或长文本自动翻译。

优点

  • 简单、轻量、零依赖
  • 切换语言时界面自动刷新
  • 可配合 trParams 处理简单动态参数(如 Hello @nameHello Tom

局限性

  • 大量文本需要手动维护
  • 不能自动识别语言环境里的新内容
  • 多语言扩展到上百条时,需要额外管理机制(如 JSON 或 CSV 文件)
使用场景类型 是否适合 GetX 多语言 说明
按钮文字 静态、结构性文本,易于维护
菜单、Tab、导航栏标题 界面固定元素,可通过 key 快速映射
提示信息 / 弹窗 提示语、验证信息等短文本适合手动翻译
App 内部固定标签 如“用户名”、“密码”、“设置”等
表格列名 / 表单标签 固定字段文本可直接定义
用户生成内容 / 评论 动态内容无法通过静态 key 映射,需要调用自动翻译服务
长篇文章 / 新闻内容 静态映射不适合大量文本,维护成本高
外部 API 返回内容 需要实时翻译或多语言处理,需要额外接口
动态生成文本 ❌ / ⚠️ 可以用 trParams 处理简单参数替换,但复杂动态文本不适合

代码讲解

translations: MyTranslations()

  • 作用:告诉 GetX 你的多语言资源在哪里。
  • 类型:必须是继承自 Translations 的类实例。
  • 原理:GetX 会根据当前语言 locale 从这个类里读取 key → 文本映射。

这里 MyTranslations 里有所有的语言映射:

'en_US': {'hello': 'Hello'},
'zh_CN': {'hello': '你好'},

当你在界面上写 'hello'.tr 时,GetX 会自动根据当前 locale 去查找对应的文本。

locale: const Locale('zh', 'CN')

  • 作用:设置应用的默认语言环境

  • 类型Locale 类的实例。

  • 当 App 启动时,GetX 会用这个语言作为初始语言。

    如果用户切换语言,可以调用:Get.updateLocale(Locale('en', 'US'));

fallbackLocale: const Locale('en', 'US')

作用:兜底语言,当当前 locale 没有对应 key 时使用。

为什么需要

  • 假设 'welcome'zh_CN 里不存在,但在 en_US 里有。
  • 使用 fallbackLocale 后,GetX 会自动使用 'en_US' 的值,而不是报错或显示空字符串。

也就是当你的 app 支持中文和英文,但某些 key 只写了英文,就不会出现缺失文本的情况。

TranslationsLocale(...)

Localed 的两个参数:Locale(String languageCode, [String? countryCode])

  • languageCode → 外层 Map 的第一部分
  • countryCode → 外层 Map 的第二部分(可选)
class MyTranslations extends Translations {
  @override
  Map<String, Map<String, String>> get keys => {
    'en_US': {'hello': 'Hello', 'welcome': 'Welcome to GetX'},
    'zh_CN': {'hello': '你好', 'welcome': '欢迎使用 GetX'},
  };
}

Locale(languageCode, countryCode) 对应Translationskeys 的 key,否则找不到文本就会用 fallbackLocale

但是不是固定的,可以自定义。比如:

外层 key(keys) Locale 对应方式
‘en_US’ Locale(‘en’, ‘US’)
‘zh_CN’ Locale(‘zh’, ‘CN’)
‘aa_bb’ Locale(‘aa’, ‘bb’)
‘cc_dd’ Locale(‘cc’, ‘dd’)

'xxxx'.tr

.trGetX 为 String 扩展的一个 getter,用来从当前语言映射表中取值。它不是 Dart 自带的属性,而是 GetX 扩展了 String 类。

// 以下是简化版的源码
extension Trans on String {
  String get tr {
    // 获取当前语言 locale
    Locale locale = Get.locale ?? Get.fallbackLocale ?? Locale('en', 'US');
    // 拼接 key(locale.languageCode + _ + countryCode)
    String langKey = '${locale.languageCode}_${locale.countryCode}';
    // 从 translations 中找对应文本
    return Get.translations?[langKey]?[this] ?? this;
  }
}

所以 'hello'.tr 的意思就是:“取当前语言环境下 key 为 'hello' 的翻译,如果找不到就返回原字符串。”

Get.locale?.languageCode

Get.locale 返回当前 应用语言环境(一个 Locale 对象)。

languageCodeLocale 的第一个参数,表示语言,比如 'en''zh'

?. 是 Dart 的空安全操作符,防止 locale 为 null。

Get.updateLocale(Locale('zh', 'CN'))

  • 作用:动态更新应用语言。
  • Locale('zh', 'CN') 是 Flutter 内置类,表示中文简体。
  • 调用后:
    1. GetX 会把当前语言更新为这个 Locale
    2. 全局所有使用 .tr 的文本都会自动刷新 UI
    3. 不需要刷新页面,GetX 会 自动触发界面重建

.trParams

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

// ------------------------ 1.创建语言类 ------------------------------
class MyTranslations extends Translations {
  @override
  Map<String, Map<String, String>> get keys => {
    // 在翻译表里写占位符(用 @参数名 标识)
    'en_US': {
      'hello': 'Hello @name',
      'welcome': 'Welcome to GetX, @name. You are @age years old.',
    },
    'zh_CN': {'hello': '你好,@name', 'welcome': '欢迎使用 GetX,@name。今年 @age 岁。'},
  };
}

// -------------------------- 2.在 GetMaterialApp 中注册 --------------------
void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'GetX i18n Demo',
      translations: MyTranslations(), // 注册翻译类
      locale: const Locale('zh', 'CN'), // 默认语言
      fallbackLocale: const Locale('en', 'US'), // 兜底语言
      home: const HomePage(),
    );
  }
}

// -------------------------- 3.在界面中使用 trParams 获取翻译文本 --------------------------

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 代码中调用 .trParams({}) 传递参数:
      appBar: AppBar(title: Text('hello'.trParams({'name': 'Tom'}))), // 单参数
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // 多参数: 是根据名字来传递的,和位置无关
            Text('welcome'.trParams({'name': 'Alice', 'age': '20'})),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                // 切换语言
                if (Get.locale?.languageCode == 'zh') {
                  Get.updateLocale(const Locale('en', 'US'));
                } else {
                  Get.updateLocale(const Locale('zh', 'CN'));
                }
              },
              child: Text('切换语言 / Switch Language'),
            ),
          ],
        ),
      ),
    );
  }
}

×

喜欢就点赞,疼爱就打赏