Introduzione
La localizzazione è un aspetto fondamentale per qualsiasi app che punti a un pubblico internazionale. In Flutter l'approccio ufficiale con flutter_localizations e intl è potente ma verboso: file ARB, generazione di codice, chiavi accessibili tramite metodi lunghi e nessun autocompletamento immediato sulle stringhe annidate.
In questo articolo vediamo slang, un package che offre una localizzazione type-safe, con autocompletamento completo, supporto a pluralizzazione, interpolazione e namespace, partendo da semplici file JSON o YAML.
Perché slang
- Type-safe: le traduzioni sono accessibili tramite oggetti generati, niente stringhe magiche.
- Autocompletamento: l'IDE suggerisce tutte le chiavi disponibili.
- Struttura annidata: puoi organizzare le traduzioni in modo gerarchico.
- Nessuna dipendenza da context (opzionale): puoi tradurre anche fuori dal widget tree.
- Pluralizzazione e genere integrati.
Installazione
Aggiungi le dipendenze al pubspec.yaml:
dependencies:
slang: ^3.31.0
slang_flutter: ^3.31.0
dev_dependencies:
slang_build_runner: ^3.31.0
build_runner: ^2.4.0
Creare i file di traduzione
Crea una cartella lib/i18n con un file per ogni lingua. Il file base è quello senza suffisso di locale.
lib/i18n/strings.i18n.json (italiano, lingua base):
{
"home": {
"title": "Benvenuto",
"greeting": "Ciao $name!",
"itemCount": {
"one": "$n elemento",
"other": "$n elementi"
}
},
"login": {
"button": "Accedi"
}
}
lib/i18n/strings_en.i18n.json (inglese):
{
"home": {
"title": "Welcome",
"greeting": "Hi $name!",
"itemCount": {
"one": "$n item",
"other": "$n items"
}
},
"login": {
"button": "Sign in"
}
}
Generare il codice
Esegui il generatore:
dart run slang
Oppure con build_runner in modalità watch:
dart run build_runner watch
Verrà creato il file strings.g.dart con tutte le classi type-safe.
Configurare l'app
Avvolgi la tua app con TranslationProvider:
import 'package:flutter/material.dart';
import 'i18n/strings.g.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
// Imposta la lingua in base al dispositivo
LocaleSettings.useDeviceLocale();
runApp(TranslationProvider(child: const MyApp()));
}
Collega i delegate di Flutter per il supporto completo:
MaterialApp(
locale: TranslationProvider.of(context).flutterLocale,
supportedLocales: AppLocaleUtils.supportedLocales,
localizationsDelegates: GlobalMaterialLocalizations.delegates,
home: const HomePage(),
)
Usare le traduzioni
Accedi alle stringhe tramite l'oggetto t, con autocompletamento completo:
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(t.home.title)),
body: Column(
children: [
Text(t.home.greeting(name: 'Marco')),
Text(t.home.itemCount(n: 3)), // -> "3 elementi"
ElevatedButton(
onPressed: () {},
child: Text(t.login.button),
),
],
),
);
}
}
Nota come l'interpolazione (name) e la pluralizzazione (n) siano parametri tipizzati: l'IDE ti segnala subito eventuali errori.
Cambiare lingua a runtime
// Cambia lingua e ricostruisce i widget sotto TranslationProvider
LocaleSettings.setLocale(AppLocale.en);
// Oppure con codice locale
LocaleSettings.setLocaleRaw('it');
Se usi context, puoi ottenere le traduzioni reattive con:
final t = Translations.of(context);
In questo modo i widget si aggiornano automaticamente al cambio di lingua.
Namespace per file multipli
Per progetti grandi puoi suddividere le traduzioni in più file abilitando i namespace nel build.yaml:
targets:
$default:
builders:
slang_build_runner:
options:
namespaces: true
Avrai file come home.i18n.json, login.i18n.json e li accederai con t.home.title, t.login.button.
slang vs intl
| Caratteristica | slang | intl/ARB |
|---|---|---|
| Type-safe | Sì, nativo | Parziale |
| Autocompletamento annidato | Ottimo | Limitato |
| Formato file | JSON/YAML/CSV | ARB |
| Traduzione fuori dal context | Sì | No |
| Standard ufficiale | No | Sì |
Conclusione
slang è un'alternativa moderna e produttiva per la localizzazione in Flutter. Se non hai vincoli sull'uso dello standard ARB, offre un'esperienza di sviluppo più fluida grazie all'autocompletamento e alla sicurezza dei tipi. Per progetti che devono integrarsi con flussi di traduzione basati su ARB, intl resta la scelta più conservativa, ma per la maggior parte delle app slang riduce sensibilmente il codice ripetitivo e gli errori.