#python#flutter#localization#automation

Automate Your Flutter App Translations with Python and Google Translate API

Sajith Lal M K
Sajith Lal M K
October 18, 20245 min read
Automate Your Flutter App Translations with Python and Google Translate API

Translating your Flutter app into multiple languages is essential for reaching a global audience, but doing it manually is time-consuming and error-prone. In this article, I'll show you how to automate the entire translation process using Python and Google Translate API.

The Problem

When building a Flutter app with internationalization (i18n), you typically:

1. Create a base English translation file (en.json)

2. Manually translate it into multiple languages

3. Keep all translations in sync when you add new features

4. Ensure consistency across 30+ language files

This process is tedious, expensive (if hiring translators), and difficult to maintain.

The Solution

I built a Python script that automatically translates your base English file into 30+ languages using Google's free translation API. The script is smart enough to:

  • Only translate missing keys (preserves existing translations)
  • Handle nested JSON structures
  • Add delays to avoid rate limiting
  • Preserve special characters and formatting
  • Prerequisites

    Before we begin, make sure you have:

  • Python 3.x installed
  • A Flutter project with localization setup
  • Basic understanding of JSON and Python
  • Install the required package:

    pip install requests

    The Complete Script

    Here's the full Python script that handles everything:

    import json
    import os
    import time
    import requests
    import html
    import random
    
    # Configuration
    BASE_LANG_FILE = 'assets/translations/en.json'
    TARGET_LANGS = ['ar', 'bg', 'cs', 'da', 'de', 'el', 'es', 'fi', 'fr', 'he', 
                    'hi', 'hu', 'id', 'it', 'ja', 'ko', 'ms', 'nb', 'nl', 'pl', 
                    'pt', 'ro', 'ru', 'sv', 'th', 'tl', 'tr', 'uk', 'vi', 'zh']
    OUTPUT_DIR = 'assets/translations'
    
    def translate_text(text, target_lang):
        if not text or text.strip() == '':
            return text
        
        try:
            # Add a delay to avoid rate limiting
            time.sleep(random.uniform(class="text-purple-400">0.5, class="text-purple-400">1.5))
            
            # Use the free Google Translate API endpoint
            url = "https://translate.googleapis.com/translate_a/single"
            params = {
                "client": "gtx",
                "sl": "en",
                "tl": target_lang,
                "dt": "t",
                "q": text
            }
            
            response = requests.get(url, params=params)
            if response.status_code == class="text-purple-400">200:
                result = response.json()
                translated_text = ''
                for part in result[class="text-purple-400">0]:
                    if part[class="text-purple-400">0]:
                        translated_text += part[class="text-purple-400">0]
                
                translated_text = html.unescape(translated_text)
                print(f"Translated '{text}' → '{translated_text}'")
                return translated_text
            else:
                print(f"Translation failed with status {response.status_code}")
                return text
        except Exception as e:
            print(f"Translation error: {e}")
            return text
    
    def load_base_language_file(filepath):
        with open(filepath, 'r', encoding='utf-8') as f:
            return json.load(f)
    
    def load_existing_translations(lang_code):
        try:
            file_path = os.path.join(OUTPUT_DIR, f"{lang_code}.json")
            if os.path.exists(file_path):
                with open(file_path, 'r', encoding='utf-8') as f:
                    return json.load(f)
        except Exception as e:
            print(f"Error loading existing translations: {e}")
        return {}
    
    def translate_dict(base_dict, target_lang, existing_translations=None):
        if existing_translations is None:
            existing_translations = {}
        
        translated = {}
        for key, value in base_dict.items():
            if key in existing_translations:
                if isinstance(value, dict) and isinstance(existing_translations[key], dict):
                    translated[key] = translate_dict(value, target_lang, existing_translations[key])
                else:
                    translated[key] = existing_translations[key]
                    print(f"Using existing translation for '{key}'")
            else:
                if isinstance(value, dict):
                    translated[key] = translate_dict(value, target_lang, {})
                elif isinstance(value, str):
                    translated[key] = translate_text(value, target_lang)
                else:
                    translated[key] = value
        return translated
    
    def save_translation_file(lang_code, data):
        os.makedirs(OUTPUT_DIR, exist_ok=True)
        file_path = os.path.join(OUTPUT_DIR, f"{lang_code}.json")
        with open(file_path, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=class="text-purple-400">2)
    
    def main():
        base_data = load_base_language_file(BASE_LANG_FILE)
        
        for lang in TARGET_LANGS:
            print(f"\nProcessing {lang}...")
            
            existing_translations = load_existing_translations(lang)
            if existing_translations:
                print(f"Found existing translations for {lang}")
            
            translated_data = translate_dict(base_data, lang, existing_translations)
            save_translation_file(lang, translated_data)
            print(f"{lang}.json saved.")
            
            time.sleep(class="text-purple-400">2)
    
    if __name__ == '__main__':
        main()

    How It Works

    1. Configuration

    The script starts by defining the base language file and target languages:

    BASE_LANG_FILE = 'assets/translations/en.json'
    TARGET_LANGS = ['ar', 'bg', 'cs', 'da', 'de', ...]
    OUTPUT_DIR = 'assets/translations'

    2. Translation Function

    The translate_text() function uses Google's free translation API:

  • Adds random delays (0.5-1.5s) to avoid rate limiting
  • Uses the gtx client (free, no API key required)
  • Handles HTML entity decoding
  • Returns original text if translation fails
  • 3. Smart Translation Merging

    The translate_dict() function is the heart of the script:

  • Recursively processes nested JSON structures
  • Checks for existing translations before making API calls
  • Only translates missing keys
  • Preserves manually corrected translations
  • 4. File Management

    The script:

  • Loads existing translation files if available
  • Creates the output directory if it doesn't exist
  • Saves translations with proper UTF-8 encoding
  • Maintains JSON formatting with indentation
  • Usage

    1. Create your base English file (assets/translations/en.json):

    {
      "app_name": "My Awesome App",
      "welcome": {
        "title": "Welcome",
        "message": "Get started with our app"
      },
      "buttons": {
        "continue": "Continue",
        "cancel": "Cancel"
      }
    }

    2. Run the script:

    python translate.py

    3. Watch the magic happen:

    The script will create 30+ translation files in your assets/translations directory.

    Key Features

    Incremental Updates

    When you add new keys to your English file, just run the script again. It will:

  • Keep all existing translations
  • Only translate the new keys
  • Save you from re-translating everything
  • Rate Limiting Protection

    The script includes:

  • Random delays between requests (0.5-1.5s)
  • 2-second delay between languages
  • Graceful error handling
  • Nested Structure Support

    The script handles complex JSON structures:

    {
      "home": {
        "header": {
          "title": "Welcome",
          "subtitle": "Start your journey"
        }
      }
    }

    Best Practices

    1. Review Translations: While Google Translate is good, always review critical translations with native speakers

    2. Use Simple English: Write clear, simple English in your base file for better translation quality

    3. Avoid Placeholders in Middle: Keep placeholders at the start or end of strings when possible

    4. Version Control: Commit your translation files to git to track changes

    5. Test Thoroughly: Test your app in different languages to ensure UI doesn't break

    Limitations

  • Free API Limits: Google may rate-limit heavy usage
  • Translation Quality: Not perfect for complex phrases or idioms
  • Context: Lacks context awareness (same word, different meanings)
  • Cultural Nuances: May miss cultural-specific expressions
  • Advanced: Customizing for Your Needs

    Add More Languages

    Simply add language codes to the TARGET_LANGS list:

    TARGET_LANGS = ['ar', 'zh', 'fr', 'de', 'custom_code']

    Exclude Certain Keys

    Modify translate_dict() to skip specific keys:

    SKIP_KEYS = ['app_name', 'api_key']
    
    if key in SKIP_KEYS:
        translated[key] = value
        continue

    Use Different Translation Services

    Replace the translate_text() function to use:

  • DeepL API (better quality, paid)
  • Microsoft Translator
  • AWS Translate
  • Any other translation service
  • Integration with Flutter

    After running the script, use the translations in your Flutter app:

    import 'package:flutter_localizations/flutter_localizations.dart';
    import 'package:easy_localization/easy_localization.dart';
    
    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await EasyLocalization.ensureInitialized();
      
      runApp(
        EasyLocalization(
          supportedLocales: [
            Locale('en'),
            Locale('ar'),
            Locale('zh'),
            // ... all your languages
          ],
          path: 'assets/translations',
          fallbackLocale: Locale('en'),
          child: MyApp(),
        ),
      );
    }

    Conclusion

    This Python script has saved me countless hours of manual translation work. Instead of spending days translating and maintaining 30+ language files, I can now:

  • Add new features in English
  • Run the script
  • Have all translations updated in minutes
  • The script is production-ready and I've used it in multiple apps with thousands of users across different countries.

    Next Steps

  • Add support for pluralization rules
  • Implement translation caching
  • Create a GUI for non-technical team members
  • Add translation quality checks
  • Happy translating! 🌍 from Sajith Lal

    Sajith Lal M K
    Sajith Lal M K

    Senior Flutter Developer with 5+ years of experience building high-performance cross-platform applications. Specialized in Flutter, Dart, Firebase & clean architecture.