I have an application that supports two languages; English and Arabic. The URL path starts with /en/home for English and /ar/home for Arabic. Language switching works fine. The issues that I am facing are:
When user switches language (clicking the button), the browser URL path does not get updated to reflect the selected language.
If the user enters the URL manually in the browser to access the Arabic version /ar/home, the page language keeps showing in English.
Below is a test code that can simulate the problem. Translation files are added as comments at the end of the code.
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:url_strategy/url_strategy.dart';
import 'package:provider/provider.dart';
var urlLang = '';
class L10n {
static final all = [
const Locale('en', ''),
const Locale('ar', ''),
];
}
Locale getSwitchToLanguage(Locale currentLocale) {
if (currentLocale == const Locale('ar', '')) {
return const Locale('en', '');
}
return const Locale('ar', '');
}
class LocaleProvider extends ChangeNotifier {
Locale _locale = const Locale('en', '');
Locale get locale => _locale;
void setLocale(Locale locale) {
if (!L10n.all.contains(locale)) return;
_locale = locale;
notifyListeners();
}
void clearLocale() {
_locale = const Locale('en', '');
notifyListeners();
}
}
void switchLanguage(BuildContext context) {
final provider = Provider.of<LocaleProvider>(context, listen: false);
final siwtchToLocale = getSwitchToLanguage(provider.locale);
provider.setLocale(siwtchToLocale);
}
void main() {
setPathUrlStrategy();
runApp(
const MyApp(),
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => ChangeNotifierProvider(
create: (context) => LocaleProvider(),
builder: (context, child) {
final provider = Provider.of<LocaleProvider>(context);
urlLang = provider.locale.languageCode;
return MaterialApp(
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: L10n.all,
locale: provider.locale,
debugShowCheckedModeBanner: false,
initialRoute: '/$urlLang/home',
// routing
onGenerateRoute: (settings) {
if (settings.name == '/ar/home' || settings.name == '/en/home') {
return MaterialPageRoute(
settings: settings, builder: (context) => const HomePage());
}
return MaterialPageRoute<void>(
settings: settings,
builder: (BuildContext context) => const UnknownScreen(),
);
},
onUnknownRoute: (settings) {
return MaterialPageRoute<void>(
settings: settings,
builder: (BuildContext context) => const UnknownScreen(),
);
},
);
},
);
}
class UnknownScreen extends StatelessWidget {
const UnknownScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("404 page"),
),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context)!.appTitle),
),
body: Center(
child: Column(children: [
const SizedBox(height: 50),
urlLang == 'ar'
? Text("This is the Arabic version : $urlLang")
: Text("This is the English version : $urlLang"),
const SizedBox(height: 100),
ElevatedButton(
child: Text(
urlLang == 'en' ? "Switch to Arabic" : "Switch to English",
),
onPressed: () {
switchLanguage(context);
},
)
]),
),
);
}
}
/*
app_en.arb file content
{
"appTitle": "Home Page",
"not_used" : "not_used"
}
app_ar.arb file content:
{
"appTitle": "الصفحة الرئيسية - Home Page",
"not_used" : "not_used"
}
*/
/*
pubspec.yaml
name: langissue
description: A new Flutter project.
publish_to: 'none'
version: 1.0.0+1
environment:
sdk: ">=2.17.3 <3.0.0"
dependencies:
flutter:
sdk: flutter
url_strategy: ^0.2.0
intl: ^0.17.0
flutter_web_plugins:
sdk: flutter
provider: ^6.0.3
async: ^2.8.2
flutter_localizations:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
flutter:
uses-material-design: true
generate: true
*/
