You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Flutter中如何通过JSON文件实现应用语言切换?

Flutter基于给定JSON结构实现多语言切换的实现方案

第一步:预处理资源与配置

  • 首先补全JSON中label_value的对应翻译值,比如法语场景下"label_value": "Nom du patient",补全后将JSON文件存放在项目assets/i18n/language_config.json路径下
  • 在pubspec.yaml中声明资源路径和依赖:
dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  shared_preferences: ^2.2.2 # 用于持久化用户选择的语言

flutter:
  assets:
    - assets/i18n/

第二步:实现本地化核心类

先将输入的扁平化JSON结构解析为按语言短码分类的翻译映射,再实现本地化委托逻辑:

import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class AppLocalizations {
  final Locale locale;
  // 存储所有语言的翻译映射:key为语言短码,value为对应翻译键值对
  static Map<String, Map<String, String>> _localizedValues = {};
  // 存储当前生效的翻译键值对
  Map<String, String> _currentLocalizedValues = {};
  // 支持的语言列表
  static List<Locale> supportedLocales = [];
  // 默认语言
  static Locale? defaultLocale;

  AppLocalizations(this.locale);

  // 方便在组件中调用的方法
  static AppLocalizations of(BuildContext context) {
    return Localizations.of<AppLocalizations>(context, AppLocalizations)!;
  }

  // 加载JSON资源并解析分组
  static Future<void> loadConfig() async {
    String jsonString = await rootBundle.loadString('assets/i18n/language_config.json');
    List<dynamic> jsonList = json.decode(jsonString);
    
    Map<String, Map<String, String>> tempMap = {};
    Set<Locale> tempLocales = {};
    Locale? tempDefaultLocale;

    for (var item in jsonList) {
      String shortCode = item['language_short_code'].toLowerCase();
      String key = item['label_key'];
      String? value = item['label_value'];
      int isDefault = item['language_is_default'];

      // 初始化当前语言的映射
      if (!tempMap.containsKey(shortCode)) {
        tempMap[shortCode] = {};
        Locale locale = Locale(shortCode);
        tempLocales.add(locale);
        if (isDefault == 1) {
          tempDefaultLocale = locale;
        }
      }
      if (value != null) {
        tempMap[shortCode]![key] = value;
      }
    }

    _localizedValues = tempMap;
    supportedLocales = tempLocales.toList();
    defaultLocale = tempDefaultLocale ?? supportedLocales.first;
  }

  // 加载当前语言的翻译
  Future<bool> load() async {
    _currentLocalizedValues = _localizedValues[locale.languageCode] ?? {};
    return true;
  }

  // 翻译方法,传入label_key返回对应翻译,不存在则返回原key
  String translate(String key) {
    return _currentLocalizedValues[key] ?? key;
  }

  // 切换语言的方法
  static Future<void> changeLanguage(BuildContext context, Locale newLocale) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setString('selected_language', newLocale.languageCode);
    // 重建应用应用新语言
    MyApp.of(context)?.setLocale(newLocale);
  }

  // 获取上次保存的语言
  static Future<Locale?> getSavedLocale() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String? code = prefs.getString('selected_language');
    if (code == null) return null;
    return Locale(code);
  }
}

// 本地化委托
class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
  final Locale? overriddenLocale;

  const AppLocalizationsDelegate({this.overriddenLocale});

  @override
  bool isSupported(Locale locale) {
    return AppLocalizations.supportedLocales.any((e) => e.languageCode == locale.languageCode);
  }

  @override
  Future<AppLocalizations> load(Locale locale) async {
    AppLocalizations localizations = AppLocalizations(overriddenLocale ?? locale);
    await localizations.load();
    return localizations;
  }

  @override
  bool shouldReload(AppLocalizationsDelegate old) => overriddenLocale != old.overriddenLocale;
}

第三步:配置根组件

将根组件改为StatefulWidget支持动态更新Locale:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // 预先加载语言配置
  await AppLocalizations.loadConfig();
  // 获取上次保存的语言
  Locale? savedLocale = await AppLocalizations.getSavedLocale();
  runApp(MyApp(initialLocale: savedLocale));
}

class MyApp extends StatefulWidget {
  final Locale? initialLocale;
  const MyApp({super.key, this.initialLocale});

  // 提供全局调用的方法更新Locale
  static MyAppState? of(BuildContext context) => context.findAncestorStateOfType<MyAppState>();

  @override
  State<MyApp> createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  Locale? _locale;

  void setLocale(Locale locale) {
    setState(() {
      _locale = locale;
    });
  }

  @override
  void initState() {
    super.initState();
    _locale = widget.initialLocale;
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '多语言Demo',
      locale: _locale,
      localizationsDelegates: const [
        AppLocalizationsDelegate(),
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: AppLocalizations.supportedLocales,
      home: const HomePage(),
    );
  }
}

第四步:业务中使用

翻译调用示例

// 会自动根据当前语言返回对应翻译
Text(AppLocalizations.of(context).translate('Patient Name'))
Text(AppLocalizations.of(context).translate('Doctor Id'))

切换语言示例

ElevatedButton(
  onPressed: () {
    AppLocalizations.changeLanguage(context, const Locale('fr'));
  },
  child: const Text('切换为法语'),
)

内容的提问来源于stack exchange,提问作者Nilrajsinh Vaghela

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 09:45:02