← Back to Blog

Complete Guide to Flutter .arb Files in 2025

flutterlocalizationarb

Complete Guide to Flutter .arb Files in 2025

Flutter's .arb (Application Resource Bundle) files are the foundation of app internationalization. If you've ever struggled with managing translations across multiple languages, you're not alone. This comprehensive guide will teach you everything you need to know about .arb files in 2025.

What are .arb Files?

.arb files are JSON-based files that store your app's translatable strings. They follow the ICU MessageFormat standard and are Flutter's preferred way to handle internationalization. Think of them as the bridge between your code and your translators.

Here's a simple example:

{
  "@@locale": "en",
  "appTitle": "My Flutter App",
  "@appTitle": {
    "description": "The title of the application"
  },
  "welcomeMessage": "Welcome, {name}!",
  "@welcomeMessage": {
    "description": "Welcome message with user name",
    "placeholders": {
      "name": {
        "type": "String"
      }
    }
  }
}

Setting Up Flutter Localization

1. Add Dependencies

First, add the necessary dependencies to your pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: any

flutter:
  generate: true

2. Configure l10n.yaml

Create an l10n.yaml file in your project root:

arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart

3. Create Your First .arb File

Create lib/l10n/app_en.arb:

{
  "@@locale": "en",
  "helloWorld": "Hello World!",
  "@helloWorld": {
    "description": "The conventional newborn programmer greeting"
  },
  "loginButton": "Login",
  "@loginButton": {
    "description": "Button text for user login"
  }
}

Advanced .arb File Features

Pluralization

Handle singular and plural forms correctly:

{
  "itemCount": "{count, plural, =0{No items} =1{One item} other{{count} items}}",
  "@itemCount": {
    "description": "Number of items in the list",
    "placeholders": {
      "count": {
        "type": "int"
      }
    }
  }
}

Gender Support

{
  "welcomeUser": "{gender, select, male{Welcome Mr. {name}} female{Welcome Ms. {name}} other{Welcome {name}}}",
  "@welcomeUser": {
    "description": "Welcome message with gender consideration",
    "placeholders": {
      "gender": {
        "type": "String"
      },
      "name": {
        "type": "String"
      }
    }
  }
}

Date and Number Formatting

{
  "currentDate": "Today is {date}",
  "@currentDate": {
    "description": "Shows the current date",
    "placeholders": {
      "date": {
        "type": "DateTime",
        "format": "yMd"
      }
    }
  },
  "priceTag": "Price: {price}",
  "@priceTag": {
    "description": "Product price display",
    "placeholders": {
      "price": {
        "type": "double",
        "format": "currency"
      }
    }
  }
}

Best Practices for .arb Files

1. Use Descriptive Keys

Bad:

{
  "button1": "Submit",
  "text2": "Welcome"
}

Good:

{
  "submitButton": "Submit",
  "welcomeMessage": "Welcome"
}

2. Always Add Descriptions

{
  "logoutConfirmation": "Are you sure you want to logout?",
  "@logoutConfirmation": {
    "description": "Confirmation dialog when user attempts to logout"
  }
}

3. Organize by Feature

{
  "@@locale": "en",
  
  // Authentication
  "loginTitle": "Login",
  "loginButton": "Sign In",
  "forgotPassword": "Forgot Password?",
  
  // Profile
  "profileTitle": "My Profile",
  "editProfile": "Edit Profile",
  "saveChanges": "Save Changes"
}

4. Handle Long Text

{
  "privacyPolicy": "By using this app, you agree to our Privacy Policy and Terms of Service. We take your privacy seriously and will never share your personal information without your consent.",
  "@privacyPolicy": {
    "description": "Privacy policy agreement text shown during registration"
  }
}

Common Pitfalls and How to Avoid Them

1. Missing Descriptions

Always provide context for translators:

{
  "save": "Save",
  "@save": {
    "description": "Button to save user profile changes"
  }
}

2. Hardcoded Plurals

Don't do this:

{
  "items": "items",
  "itemsText": "You have {count} items"
}

Do this:

{
  "itemCount": "{count, plural, =0{No items} =1{One item} other{{count} items}}",
  "@itemCount": {
    "placeholders": {
      "count": {"type": "int"}
    }
  }
}

3. Concatenating Strings

Avoid:

{
  "hello": "Hello",
  "username": "Username:",
  "fullGreeting": "Hello, Username: John"
}

Better:

{
  "userGreeting": "Hello, {username}!",
  "@userGreeting": {
    "placeholders": {
      "username": {"type": "String"}
    }
  }
}

Using Generated Localizations in Your Code

After running flutter gen-l10n, use your translations like this:

import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final l10n = AppLocalizations.of(context)!;
    
    return Scaffold(
      appBar: AppBar(
        title: Text(l10n.appTitle),
      ),
      body: Column(
        children: [
          Text(l10n.welcomeMessage('John')),
          Text(l10n.itemCount(5)),
          ElevatedButton(
            onPressed: () {},
            child: Text(l10n.loginButton),
          ),
        ],
      ),
    );
  }
}

Managing Multiple Languages

Directory Structure

lib/
  l10n/
    app_en.arb    # English (template)
    app_es.arb    # Spanish
    app_fr.arb    # French
    app_de.arb    # German

Spanish Example (app_es.arb)

{
  "@@locale": "es",
  "appTitle": "Mi Aplicación Flutter",
  "welcomeMessage": "¡Bienvenido, {name}!",
  "loginButton": "Iniciar Sesión",
  "itemCount": "{count, plural, =0{Sin elementos} =1{Un elemento} other{{count} elementos}}"
}

Validating Your .arb Files

1. Check JSON Syntax

Ensure your .arb files are valid JSON. Use a JSON validator or your IDE's JSON validation.

2. Verify Placeholders Match

Make sure all placeholders in translations match the template:

// app_en.arb
{
  "greeting": "Hello, {name} from {city}!",
  "@greeting": {
    "placeholders": {
      "name": {"type": "String"},
      "city": {"type": "String"}
    }
  }
}

// app_es.arb
{
  "greeting": "¡Hola, {name} de {city}!"
}

3. Test Pluralization

Test your plural forms with different values:

// Test with 0, 1, 2, 5, 100
Text(l10n.itemCount(0)),  // "No items"
Text(l10n.itemCount(1)),  // "One item"  
Text(l10n.itemCount(5)),  // "5 items"

Automation and Tools

1. FlutterLocalisation Platform

Instead of managing .arb files manually, consider using FlutterLocalisation to:

  • Automatically sync .arb files with your Git repository
  • Collaborate with translators in a visual interface
  • Use AI-powered translation suggestions
  • Validate your .arb files automatically
  • Manage team access with role-based permissions

2. VS Code Extensions

Install helpful extensions:

  • Flutter Intl: Generates boilerplate code
  • i18n Ally: Visualizes your translations
  • JSON Tools: Formats and validates JSON

3. CI/CD Integration

Add .arb validation to your CI pipeline:

# .github/workflows/flutter.yml
- name: Validate ARB files
  run: |
    find lib/l10n -name "*.arb" -exec python -m json.tool {} \;
    flutter gen-l10n

Performance Considerations

1. Lazy Loading

For large apps, consider lazy loading translations:

class AppLocalizations {
  static Future<AppLocalizations> load(Locale locale) async {
    // Load only the required locale
    return AppLocalizations._();
  }
}

2. Caching

Cache frequently used translations:

class TranslationCache {
  static final Map<String, String> _cache = {};
  
  static String get(String key, AppLocalizations l10n) {
    return _cache[key] ??= _getTranslation(key, l10n);
  }
}

Debugging Translation Issues

1. Missing Translations

class DebugLocalizations extends AppLocalizations {
  @override
  String getString(String key) {
    final value = super.getString(key);
    if (value == key) {
      print('Missing translation for: $key');
    }
    return value;
  }
}

2. Placeholder Issues

String safeFormat(String template, Map<String, dynamic> args) {
  try {
    return template.replaceAllMapped(
      RegExp(r'\{(\w+)\}'),
      (match) => args[match.group(1)]?.toString() ?? match.group(0)!,
    );
  } catch (e) {
    print('Format error in: $template');
    return template;
  }
}

Real-World Example: E-commerce App

Here's a complete .arb file for an e-commerce app:

{
  "@@locale": "en",
  
  // Navigation
  "homeTab": "Home",
  "searchTab": "Search", 
  "cartTab": "Cart",
  "profileTab": "Profile",
  
  // Product Listing
  "productCount": "{count, plural, =0{No products found} =1{1 product} other{{count} products}}",
  "@productCount": {
    "description": "Number of products in search results",
    "placeholders": {
      "count": {"type": "int"}
    }
  },
  
  "priceRange": "Price: {minPrice} - {maxPrice}",
  "@priceRange": {
    "description": "Price range for products",
    "placeholders": {
      "minPrice": {"type": "double", "format": "currency"},
      "maxPrice": {"type": "double", "format": "currency"}
    }
  },
  
  // Shopping Cart
  "addToCart": "Add to Cart",
  "@addToCart": {
    "description": "Button to add product to shopping cart"
  },
  
  "cartTotal": "Total: {amount}",
  "@cartTotal": {
    "description": "Total amount in shopping cart",
    "placeholders": {
      "amount": {"type": "double", "format": "currency"}
    }
  },
  
  // Checkout
  "checkoutTitle": "Checkout",
  "shippingAddress": "Shipping Address",
  "paymentMethod": "Payment Method",
  "orderSummary": "Order Summary",
  
  "estimatedDelivery": "Estimated delivery: {date}",
  "@estimatedDelivery": {
    "description": "Expected delivery date",
    "placeholders": {
      "date": {"type": "DateTime", "format": "MMMd"}
    }
  }
}

Conclusion

Mastering .arb files is crucial for creating truly international Flutter apps. By following these best practices, you'll create maintainable, translator-friendly, and robust internationalization systems.

Remember:

  • Always provide context with descriptions
  • Use semantic key names
  • Handle pluralization properly
  • Validate your files regularly
  • Consider automation tools for larger projects

Ready to streamline your Flutter localization workflow? Try FlutterLocalisation for automated .arb file management with Git integration, team collaboration, and AI-powered translations.


Next Steps:

  1. Set up your first .arb files using this guide
  2. Test with multiple languages
  3. Integrate validation into your development workflow
  4. Consider automation tools as your project grows

Have questions about Flutter localization? Feel free to reach out - we're here to help!