Central de Ajuda

Localização Flutter: Arquivos ARB, Intl e Automação

O sistema de localização nativo do Flutter utiliza arquivos Application Resource Bundle (ARB) e o pacote intl para oferecer experiências totalmente nativas em qualquer idioma. Este guia abrange desde a configuração do projeto e detalhes do formato ARB até troca de idioma, pluralização e automação de traduções com l10n.dev.

O que é Localização Flutter?

Localização Flutter é a abordagem oficial para adaptar seu app para múltiplos idiomas e regiões. Baseia-se em arquivos ARB para armazenar strings traduzidas e no gerador de código flutter_gen para produzir acessores Dart com tipagem segura. Em tempo de execução, o Flutter seleciona o arquivo ARB correto com base na localidade do dispositivo — sem necessidade de reiniciar ao trocar de idioma programaticamente.

Configuração do Projeto

O pipeline de localização do Flutter é guiado por dois arquivos de configuração: pubspec.yaml e l10n.yaml. Ative a geração de código no pubspec.yaml e aponte o Flutter para o diretório dos seus arquivos ARB.

1. Atualize o pubspec.yaml

Adicione flutter_localizations e intl como dependências e ative a flag generate para que o Flutter gere automaticamente as classes Dart de localização a partir dos seus arquivos ARB.

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

flutter:
  generate: true

2. Crie o l10n.yaml

Coloque um arquivo l10n.yaml na raiz do seu projeto para configurar o diretório ARB, o arquivo modelo e o nome do arquivo de saída gerado.

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

Formato do Arquivo ARB

ARB (Application Resource Bundle) é um formato baseado em JSON projetado especificamente para internacionalização Flutter. Cada chave corresponde a uma string traduzível, e chaves de metadados opcionais (prefixadas com @) contêm descrições, definições de espaços reservados e contexto para tradutores.

  • @@locale: Declara a localidade do arquivo (ex.: "en", "fr", "zh_CN"). O l10n.dev atualiza automaticamente para o código do idioma alvo.
  • @@last_modified: Carimbo de data/hora da última modificação. O l10n.dev define automaticamente para o timestamp UTC atual ao gerar arquivos traduzidos.
  • Metadados @key: Entradas de metadados como descrição, exemplo e espaços reservados NÃO são traduzidas por padrão — permanecem inalteradas para preservar o contexto para tradutores. Ative a configuração translateMetadata se desejar traduzi-las.
  • Espaços reservados e mensagens ICU: Strings podem conter espaços reservados nomeados ({name}) e sintaxe de mensagens ICU para pluralização e seleção — todos preservados corretamente durante a tradução.

Arquivo ARB fonte (Inglês)

{
  "@@locale": "en",
  "@@last_modified": "2026-01-15T10:30:00Z",

  "appTitle": "My App",
  "@appTitle": {
    "description": "The title of the application"
  },

  "welcome": "Welcome, {name}!",
  "@welcome": {
    "description": "Welcome message shown on the home screen",
    "placeholders": {
      "name": {
        "type": "String",
        "example": "Alice"
      }
    }
  },

  "unreadMessages": "{count, plural, =0{No unread messages} =1{1 unread message} other{{count} unread messages}}",
  "@unreadMessages": {
    "description": "Number of unread messages",
    "placeholders": {
      "count": {
        "type": "int"
      }
    }
  }
}

Arquivo ARB traduzido (Francês)

Após a tradução, as strings da interface são localizadas enquanto a estrutura dos metadados permanece intacta. O l10n.dev atualiza @@locale e @@last_modified automaticamente.

{
  "@@locale": "fr",
  "@@last_modified": "2026-01-15T10:30:01Z",

  "appTitle": "Mon Application",
  "@appTitle": {
    "description": "The title of the application"
  },

  "welcome": "Bienvenue, {name} !",
  "@welcome": {
    "description": "Welcome message shown on the home screen",
    "placeholders": {
      "name": {
        "type": "String",
        "example": "Alice"
      }
    }
  },

  "unreadMessages": "{count, plural, =0{Aucun message non lu} =1{1 message non lu} other{{count} messages non lus}}",
  "@unreadMessages": {
    "description": "Number of unread messages",
    "placeholders": {
      "count": {
        "type": "int"
      }
    }
  }
}

Convenções de Nomeação de Arquivos

Arquivos ARB seguem um padrão simples de nomeação: um prefixo (por padrão app_) seguido do código da localidade e a extensão .arb. Flutter e l10n.dev usam underscores para separar códigos de idioma e região.

Arquivos ARB usam underscores, não hífens — escreva app_en_US.arb e app_zh_CN.arb, não app_en-US.arb ou app_zh-CN.arb.
# Default pattern (recommended)
app_en.arb
app_fr.arb
app_en_US.arb          # Locale with region (underscore format)
app_zh_CN.arb          # Chinese Simplified

# Custom prefix patterns also supported
my_app_en.arb
my_app_fr.arb

# Note: ARB files use underscores, not hyphens
# ✓  app_en_US.arb
# ✗  app_en-US.arb

Estrutura do Projeto

Organize todos os seus arquivos ARB dentro de uma pasta dedicada l10n dentro de lib/. O gerador de código do Flutter os detecta automaticamente com base na configuração arb-dir do l10n.yaml e gera classes Dart prontas para uso.

lib/
├── l10n/
│   ├── app_en.arb        ← Source (English)
│   ├── app_fr.arb        ← French
│   ├── app_de.arb        ← German
│   ├── app_ja.arb        ← Japanese
│   ├── app_zh_CN.arb     ← Chinese Simplified
│   └── app_es.arb        ← Spanish
├── main.dart
└── ...

# Generated output (do not edit manually)
.dart_tool/
└── flutter_gen/
    └── gen_l10n/
        └── app_localizations.dart

Inicialização

Conecte a classe Dart de localização gerada ao MaterialApp fornecendo localizationsDelegates e supportedLocales. O Flutter então resolve os dados ARB corretos para a localidade do dispositivo.

Configuração do MaterialApp

Passe os quatro delegates necessários — seu AppLocalizations.delegate gerado mais os três delegates do SDK Flutter — e liste todas as localidades que seu app suporta. Use AppLocalizations.of(context)! em qualquer lugar da árvore de widgets para acessar strings traduzidas.

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'My App',

      // Required delegates
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],

      // Supported locales
      supportedLocales: AppLocalizations.supportedLocales,

      home: const HomePage(),
    );
  }
}

// Use in a widget
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    final l10n = AppLocalizations.of(context)!;

    return Scaffold(
      appBar: AppBar(title: Text(l10n.appTitle)),
      body: Center(child: Text(l10n.welcome('Alice'))),
    );
  }
}

Troca de Idioma em Tempo de Execução

O Flutter permite trocar a localidade do app em tempo de execução atualizando a propriedade locale do MaterialApp. Um padrão comum é armazenar um Locale em um StatefulWidget ou solução de gerenciamento de estado e expor um callback para alterá-lo. A árvore de widgets se reconstrói automaticamente com a nova localidade.

// Manage locale state at the app level
class MyApp extends StatefulWidget {
  const MyApp({super.key});

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

class _MyAppState extends State<MyApp> {
  Locale _locale = const Locale('en');

  void _changeLocale(Locale locale) {
    setState(() => _locale = locale);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      locale: _locale,
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: AppLocalizations.supportedLocales,
      home: SettingsPage(onLocaleChange: _changeLocale),
    );
  }
}

// Language selector widget
class LanguageSelector extends StatelessWidget {
  final void Function(Locale) onLocaleChange;

  const LanguageSelector({super.key, required this.onLocaleChange});

  @override
  Widget build(BuildContext context) {
    return DropdownButton<Locale>(
      value: Localizations.localeOf(context),
      items: AppLocalizations.supportedLocales
          .map((locale) => DropdownMenuItem(
                value: locale,
                child: Text(locale.toLanguageTag()),
              ))
          .toList(),
      onChanged: (locale) {
        if (locale != null) onLocaleChange(locale);
      },
    );
  }
}

Pluralização

Flutter usa a sintaxe de mensagens ICU para pluralização dentro dos arquivos ARB. O pacote intl lida com todas as categorias plurais do CLDR, aplicando automaticamente a forma correta conforme as regras do idioma alvo.

  • Use a sintaxe {count, plural, =0{...} =1{...} other{...}} dentro dos valores das strings ARB.
  • Declare o placeholder count com tipo int nos metadados @key.
  • O l10n.dev gera todas as formas plurais necessárias para cada idioma alvo — incluindo idiomas complexos como árabe, russo e polonês — sem intervenção manual.
{
  "cartItems": "{count, plural, =0{Your cart is empty} =1{1 item in your cart} other{{count} items in your cart}}",
  "@cartItems": {
    "description": "Cart item count",
    "placeholders": {
      "count": { "type": "int" }
    }
  },

  "daysLeft": "{days, plural, =1{1 day left} other{{days} days left}}",
  "@daysLeft": {
    "description": "Days remaining",
    "placeholders": {
      "days": { "type": "int" }
    }
  }
}

Suporte Completo a ARB no l10n.dev

O l10n.dev foi criado para funcionar perfeitamente com o fluxo de trabalho ARB do Flutter. Faça upload do seu arquivo ARB fonte e receba traduções precisas e corretamente estruturadas de volta:

  • Atualizações Automáticas de Metadados: @@locale é atualizado para o código do idioma alvo e @@last_modified é definido automaticamente para o timestamp UTC atual.
  • Controle de Tradução de Metadados: Por padrão, entradas de metadados @key (descrição, exemplo, contexto) NÃO são traduzidas e permanecem inalteradas, mantendo as notas para tradutores intactas. Ative a configuração translateMetadata para traduzi-las junto com as strings da interface.
  • Prefixos Personalizados de Arquivo: Qualquer padrão de nomeação é suportado — app_en.arb, my_app_en_US.arb, strings_fr.arb e outros.
  • Formato de Localidade com Underscore: Códigos de localidade ARB usam underscores (en_US, zh_CN) em vez de hífens — o l10n.dev trata isso corretamente para que os arquivos gerados caiam direto no seu projeto Flutter.
  • Consciência de Pluralização: Formas plurais ICU são geradas para cada idioma alvo conforme as regras CLDR, sem necessidade de edição manual após a tradução.

Automatize Traduções com npm

Use o pacote npm ai-l10n para traduzir seu arquivo ARB fonte via linha de comando ou como parte de um pipeline CI/CD. Instale uma vez e traduza para qualquer número de idiomas com um único comando.

# Install the CLI
npm install ai-l10n

# Translate your source ARB to multiple languages
npx ai-l10n translate lib/l10n/app_en.arb \
  --languages fr,de,ja,zh_CN,es,ko

Integração em um build do Flutter

Você pode conectar o ai-l10n diretamente ao seu processo de build do Flutter para que as traduções estejam sempre atualizadas antes que o aplicativo seja compilado. Duas abordagens comuns são um script no package.json ou um Makefile.

Via scripts do package.json

Adicione um script de tradução e use o gancho de ciclo de vida prebuild do npm para executá-lo automaticamente antes de cada build. Execute npm run build:android (ou build:ios / build:web) e o ai-l10n traduzirá primeiro, depois passará o processo para o Flutter.

{
  "scripts": {
    "translate": "ai-l10n translate lib/l10n/app_en.arb --languages fr,de,ja,zh_CN,es,ko --update",
    "prebuild": "npm run translate",
    "build:android": "flutter build apk",
    "build:ios": "flutter build ios",
    "build:web": "flutter build web"
  }
}

Via Makefile

Se sua equipe usa Make, declare um alvo (target) de tradução e faça com que cada alvo de build dependa dele. Executar make build-android (ou build-ios / build-all) traduzirá todos os idiomas de destino antes de invocar o flutter build.

LANGUAGES = fr,de,ja,zh_CN,es,ko

translate:
	npx ai-l10n translate lib/l10n/app_en.arb --languages $(LANGUAGES) --update

build-android: translate
	flutter build apk

build-ios: translate
	flutter build ios

build-web: translate
	flutter build web

build-all: translate
	flutter build apk
	flutter build ios
	flutter build web

Para integração CI/CD, atualizações incrementais, tradução em lote de múltiplos arquivos e exemplos de workflow no GitHub Actions, veja o Guia de Automação de Localização.

Extensão VS Code

A extensão l10n.dev para VS Code traz a tradução de arquivos ARB Flutter diretamente para seu editor. Clique com o botão direito em qualquer arquivo ARB e traduza para seus idiomas alvo sem sair do VS Code.

Como Funciona no VS Code:

  1. Abra seu arquivo ARB fonte (ex.: app_en.arb) no editor.
  2. Clique com o botão direito no editor e selecione "Translate JSON".
  3. Escolha um ou mais idiomas alvo (ex.: Francês, Japonês, Alemão).
  4. A extensão cria arquivos ARB localizados ao lado do seu arquivo fonte, atualizando @@locale e @@last_modified automaticamente.

Veja em Ação

Aqui está um exemplo ao vivo de tradução de um arquivo ARB Flutter para uzbeque dentro do VS Code:

Flutter ARB localization in VS Code

Comece a Localizar Seu App Flutter

Pronto para alcançar usuários globais? Você pode traduzir arquivos ARB diretamente no workspace l10n.dev, automatizar com o CLI npm ou traduzir direto no VS Code: