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

如何借助自有翻译API实现Flutter应用的本地化?

How to Localize Your Flutter App with a Custom Translation API

Got it, let's walk through how to hook up your custom translation API to handle localization in your Flutter app. I'll break this down into actionable steps that fit with Flutter's localization system, plus we'll work with the API response format you shared.

1. Build a Core Translation Service

First, create a dedicated service class to handle API calls, parse responses, and manage translated strings. This keeps your API logic clean and separate from the UI layer.

You'll need the http package first—add it to your pubspec.yaml under dependencies:

dependencies:
  flutter:
    sdk: flutter
  http: ^1.1.0

Here's the service implementation tailored to your API response:

import 'dart:convert';
import 'package:http/http.dart' as http;

class TranslationService {
  final String apiBaseUrl;

  TranslationService(this.apiBaseUrl);

  // Fetch translations for a target locale
  Future<Map<String, String>> fetchTranslations(String locale) async {
    try {
      final response = await http.post(
        Uri.parse('$apiBaseUrl/translate'), // Adjust to your actual endpoint
        body: {'target_locale': locale}, // Send locale as a request parameter
      );

      if (response.statusCode == 200) {
        final data = json.decode(response.body);
        // Parse your API's specific response structure
        if (data['status'] == 'success' && data['result'] is List) {
          final translations = <String, String>{};
          // Merge all translation objects from the result list into one map
          for (final item in data['result']) {
            if (item is Map<String, dynamic>) {
              translations.addAll(item.cast<String, String>());
            }
          }
          return translations;
        } else {
          throw Exception('Failed to parse translation response');
        }
      } else {
        throw Exception('API request failed with status: ${response.statusCode}');
      }
    } catch (e) {
      print('Translation API error: $e');
      // Fallback to default strings if API call fails
      return {'hello': 'hello'};
    }
  }
}

2. Create a Custom Localization Delegate

Flutter uses LocalizationsDelegate to load localized strings. We'll build a custom delegate that uses our TranslationService to fetch strings from the API.

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

class AppLocalizations {
  final Map<String, String> translations;

  AppLocalizations(this.translations);

  // Helper method to get translated strings by key
  String translate(String key) {
    return translations[key] ?? key; // Return key if translation is missing
  }

  // Static method to access translations from any widget context
  static AppLocalizations of(BuildContext context) {
    return Localizations.of<AppLocalizations>(context, AppLocalizations)!;
  }
}

class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
  final TranslationService translationService;
  final List<Locale> supportedLocales;

  AppLocalizationsDelegate({
    required this.translationService,
    required this.supportedLocales,
  });

  @override
  bool isSupported(Locale locale) {
    // Check if the locale is in our supported list
    return supportedLocales.any((l) => l.languageCode == locale.languageCode);
  }

  @override
  Future<AppLocalizations> load(Locale locale) async {
    // Fetch translations for the current locale
    final translations = await translationService.fetchTranslations(locale.languageCode);
    return AppLocalizations(translations);
  }

  @override
  bool shouldReload(covariant LocalizationsDelegate<AppLocalizations> old) {
    // Return true if you want to reload translations when the app state changes
    return false;
  }
}

3. Integrate with Your Flutter App

Wire up the delegate and service in your main app widget to make translations available across your app:

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    // Initialize your translation service with your API base URL
    final translationService = TranslationService('https://your-api-domain.com');
    // Define locales your API supports
    final supportedLocales = const [
      Locale('en'),
      Locale('es'),
      Locale('fr'),
      // Add more locales as needed
    ];

    return MaterialApp(
      title: 'Custom Localization Demo',
      localizationsDelegates: [
        AppLocalizationsDelegate(
          translationService: translationService,
          supportedLocales: supportedLocales,
        ),
        // Keep default delegates for system widgets (date pickers, etc.)
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: supportedLocales,
      home: const HomeScreen(),
    );
  }
}

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

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

4. Add Caching (Critical for Performance)

Calling the API every time the app loads or the locale changes isn't efficient. Add a caching layer using shared_preferences to store fetched translations locally.

First add shared_preferences to your pubspec.yaml:

dependencies:
  # ... other dependencies
  shared_preferences: ^2.2.2

Update the TranslationService to include caching:

import 'package:shared_preferences/shared_preferences.dart';

class TranslationService {
  final String apiBaseUrl;
  late SharedPreferences _prefs;

  TranslationService(this.apiBaseUrl) {
    _initPrefs();
  }

  Future<void> _initPrefs() async {
    _prefs = await SharedPreferences.getInstance();
  }

  Future<Map<String, String>> fetchTranslations(String locale) async {
    // Check cache first
    final cachedTranslations = _prefs.getString('translations_$locale');
    if (cachedTranslations != null) {
      return Map<String, String>.from(json.decode(cachedTranslations));
    }

    // If no cache, call API
    try {
      final response = await http.post(
        Uri.parse('$apiBaseUrl/translate'),
        body: {'target_locale': locale},
      );

      if (response.statusCode == 200) {
        final data = json.decode(response.body);
        if (data['status'] == 'success' && data['result'] is List) {
          final translations = <String, String>{};
          for (final item in data['result']) {
            if (item is Map<String, dynamic>) {
              translations.addAll(item.cast<String, String>());
            }
          }
          // Save to cache for future use
          await _prefs.setString('translations_$locale', json.encode(translations));
          return translations;
        } else {
          throw Exception('Failed to parse translation response');
        }
      } else {
        throw Exception('API request failed with status: ${response.statusCode}');
      }
    } catch (e) {
      print('Translation API error: $e');
      return {'hello': 'hello'};
    }
  }
}

5. Handle Edge Cases

  • API Failures: Always include fallback strings so your app doesn't break if the API is unavailable.
  • Auto-Detect Locale: Use window.locale (from dart:ui) to automatically set the user's device locale on startup.
  • Dynamic Locale Switching: Add a settings screen to let users change locales, then use state management (like Provider or Riverpod) to reload localizations.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 17:12:37