Central de Ajuda

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

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

O que é a Localização no Flutter?

A localização no Flutter é a abordagem oficial para adaptar seu aplicativo para vários idiomas e regiões. Ela depende de arquivos ARB para armazenar strings traduzidas e do gerador de código flutter_gen para produzir acessadores Dart com segurança de tipo. Em tempo de execução, o Flutter seleciona o arquivo ARB correto com base no local do dispositivo - sem necessidade de reiniciar ao alternar locais programaticamente.

Configuração do Projeto

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

1. Atualize o pubspec.yaml

Adicione flutter_localizations e intl como dependências e, em seguida, habilite a flag generate para que o Flutter gere automaticamente as classes de localização Dart a partir de 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 de 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

O Formato de Arquivo ARB

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

  • @@locale: Declara o local do arquivo (por exemplo, "en", "fr", "zh_CN"). O l10n.dev atualiza isso automaticamente para o código do idioma de destino.
  • @@last_modified: Carimbo de data/hora da última modificação. O l10n.dev define isso automaticamente para o carimbo de data/hora UTC atual ao gerar arquivos traduzidos.
  • Metadados @key: Entradas de metadados como descrição, exemplo e placeholders NÃO são traduzidas por padrão - elas permanecem inalteradas para preservar o contexto para os tradutores. Habilite a configuração translateMetadata se desejar que elas sejam traduzidas.
  • Placeholders e mensagens ICU: As strings podem conter placeholders nomeados ({name}) e sintaxe de mensagem ICU para pluralização e seleção - tudo isso é preservado corretamente durante a tradução.

Arquivo ARB de origem (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 UI são localizadas enquanto a estrutura de 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 Nomenclatura de Arquivos

Os arquivos ARB seguem um padrão de nomenclatura simples: um prefixo (por padrão app_) seguido pelo código do local e a extensão .arb. O Flutter e o l10n.dev usam sublinhados para separar códigos de idioma e região.

Arquivos ARB usam sublinhados, não hifens - 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 l10n dedicada em lib/. O gerador de código do Flutter os detecta automaticamente com base na configuração arb-dir no 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 de localização Dart gerada ao MaterialApp fornecendo localizationsDelegates e supportedLocales. O Flutter resolverá os dados ARB corretos para o local do dispositivo.

Configuração do MaterialApp

Passe os quatro delegados necessários - seu AppLocalizations.delegate gerado mais os três delegados do SDK do Flutter - e liste todos os locais que seu aplicativo suporta. Use AppLocalizations.of(context)! em qualquer lugar na á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 que você alterne o local do aplicativo em tempo de execução atualizando a propriedade locale no MaterialApp. Um padrão comum é manter um Locale em um StatefulWidget ou em uma solução de gerenciamento de estado e expor um callback para alterá-lo. A árvore de widgets é reconstruída automaticamente com o novo local.

// 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

O Flutter usa a sintaxe de mensagem ICU para pluralização dentro de arquivos ARB. O pacote intl lida com todas as categorias de plural do CLDR, aplicando automaticamente a forma correta com base nas regras do idioma de destino.

  • Use a sintaxe {count, plural, =0{...} =1{...} other{...}} dentro dos valores de string ARB.
  • Declare o placeholder count com o tipo int nos metadados @key.
  • O l10n.dev gera todas as formas plurais necessárias para cada idioma de destino - 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 Total a ARB no l10n.dev

O l10n.dev foi criado especificamente para funcionar perfeitamente com o fluxo de trabalho ARB do Flutter. Envie seu arquivo ARB de origem e receba traduções precisas e estruturadas corretamente:

  • Atualizações Automáticas de Metadados: @@locale é atualizado para o código do idioma de destino e @@last_modified é definido automaticamente para o carimbo de data/hora UTC atual.
  • Controle de Tradução de Metadados: Por padrão, as entradas de metadados @key (descrição, exemplo, contexto) NÃO são traduzidas e permanecem inalteradas, mantendo as notas do tradutor intactas. Habilite a configuração translateMetadata para traduzi-las junto com as strings da UI.
  • Prefixos de Arquivo Personalizados: Qualquer padrão de nomenclatura é suportado - app_en.arb, my_app_en_US.arb, strings_fr.arb e muito mais.
  • Formato de Local com Sublinhado: Os códigos de local ARB usam sublinhados (en_US, zh_CN) em vez de hifens - o l10n.dev lida com isso corretamente para que os arquivos gerados sejam inseridos diretamente no seu projeto Flutter.
  • Ciente da Pluralização: As formas plurais ICU são geradas para cada idioma de destino de acordo com as regras do CLDR, portanto, nenhuma edição manual de plural é necessária após a tradução.

Automatize Traduções com npm

Use o pacote npm ai-l10n para traduzir seu arquivo ARB de origem a partir da linha de comando ou como parte de um pipeline de CI/CD. Instale uma vez e traduza para qualquer número de idiomas em 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 package.json ou um Makefile.

Via scripts package.json

Adicione um script de tradução e use o hook 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 e, em seguida, passará 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 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 de CI/CD, atualizações incrementais, tradução em lote em vários arquivos e exemplos de fluxo de trabalho do GitHub Actions, consulte o Guia de Automação de Localização.

Extensão para VS Code

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

Como Funciona no VS Code:

  1. Abra seu arquivo ARB de origem (por exemplo, app_en.arb) no editor.
  2. Clique com o botão direito no editor e selecione "Translate JSON".
  3. Escolha um ou mais idiomas de destino (por exemplo, francês, japonês, alemão).
  4. A extensão cria arquivos ARB localizados ao lado da sua origem, com @@locale e @@last_modified atualizados automaticamente.

Veja em Ação

Aqui está um exemplo ao vivo de como traduzir um arquivo ARB do Flutter para uzbeque dentro do VS Code:

Flutter ARB localization in VS Code

Comece a Localizar seu Aplicativo Flutter

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