Skip to content

Commit

Permalink
Merge pull request #1461 from atsign-foundation/1303-featnpt-flutterl…
Browse files Browse the repository at this point in the history
…ocalize-relay-selection

feat: Added Localisation for English, Portuguese, Spanish, Mandarin and Cantonese
  • Loading branch information
CurtlyCritchlow authored Oct 21, 2024
2 parents 40fbe71 + 3b48f1f commit 326533b
Show file tree
Hide file tree
Showing 23 changed files with 735 additions and 212 deletions.
18 changes: 14 additions & 4 deletions packages/dart/npt_flutter/lib/app.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:npt_flutter/features/features.dart';
import 'package:npt_flutter/routes.dart';
import 'package:npt_flutter/styles/app_theme.dart';
import 'package:npt_flutter/util/language.dart';

export 'package:npt_flutter/features/logging/logging.dart';

Expand Down Expand Up @@ -91,21 +94,28 @@ class App extends StatelessWidget {
create: (ctx) => FavoriteBloc(ctx.read<FavoriteRepository>()),
),
],
child: BlocSelector<SettingsBloc, SettingsState, Language>(selector: (state) {
child: BlocSelector<SettingsBloc, SettingsState, Language?>(selector: (state) {
if (state is SettingsLoadedState) {
return state.settings.language;
}

return Language.english;
return null;
}, builder: (context, language) {
Locale? defaultLocal;
if (language == null) {
//check if the device language is supported, if not use english as the default.

defaultLocal = LanguageUtil.getLanguageFromLocale(Locale(Platform.localeName)).locale;
}

return TrayManager(
child: MaterialApp(
theme: AppTheme.light(),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
locale: language.locale,
locale: language != null ? language.locale : defaultLocal,
localeResolutionCallback: (locale, supportedLocales) {
return language.locale;
return language != null ? language.locale : locale;
},
navigatorKey: navState,
initialRoute: Routes.onboarding,
Expand Down
15 changes: 5 additions & 10 deletions packages/dart/npt_flutter/lib/constants.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';


class Constants {
static String? get namespace => 'noports';
Expand All @@ -10,16 +12,9 @@ class Constants {
static const pngIconLight = 'assets/noports-icon64-light.png';
static const icoIconLight = 'assets/noports-icon64-light.ico';

static const Map<String, String> defaultRelayOptions = {
"@rv_am": "Los Angeles",
"@rv_eu": "London",
"@rv_ap": "Singapore",
};

static Map<String, String> getRootDomains(BuildContext context) {
// TODO localize right hand side of map
return {'root.atsign.org': 'Default (Prod)', 'vip.ve.atsign.zone': 'Demo (VE)'};
}
AppLocalizations strings = AppLocalizations.of(context)!;

static const languages = ['English', 'Spanish', 'Br portuguese', 'Mandarin', 'Cantonese'];
return {'root.atsign.org': strings.rootDomainDefault, 'vip.ve.atsign.zone': strings.rootDomainDemo};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,7 @@ class OnboardingView extends StatelessWidget {
bottom: Sizes.p44,
right: Sizes.p44,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
CustomTextButton.resetAtsign(),
],
),
child: CustomTextButton.resetAtsign(),
),
)
],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:developer';
import 'dart:io';

import 'package:at_contacts_flutter/at_contacts_flutter.dart';
import 'package:at_onboarding_flutter/at_onboarding_flutter.dart';
Expand All @@ -11,6 +12,8 @@ import 'package:npt_flutter/features/onboarding/onboarding.dart';
import 'package:npt_flutter/features/onboarding/util/atsign_manager.dart';
import 'package:npt_flutter/features/onboarding/widgets/onboarding_dialog.dart';
import 'package:npt_flutter/routes.dart';
import 'package:npt_flutter/util/language.dart';

import 'package:path_provider/path_provider.dart';
import 'package:phosphor_flutter/phosphor_flutter.dart';

Expand Down Expand Up @@ -64,7 +67,7 @@ class _OnboardingButtonState extends State<OnboardingButton> {
// hours for this tiny UX fix

// TODO: fix localizations
await AtOnboardingLocalizations.load(const Locale("en"));
await AtOnboardingLocalizations.load(LanguageUtil.getLanguageFromLocale(Locale(Platform.localeName)).locale);
onboardingResult = await Navigator.push(
// ignore: use_build_context_synchronously
context,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:npt_flutter/features/profile/profile.dart';
import 'package:npt_flutter/styles/sizes.dart';

Expand All @@ -8,16 +9,17 @@ class ProfileStatusIndicator extends StatelessWidget {

@override
Widget build(BuildContext context) {
final strings = AppLocalizations.of(context)!;
return Expanded(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: BlocBuilder<ProfileBloc, ProfileState>(builder: (BuildContext context, ProfileState state) {
if (state is ProfileFailedSave) {
return const Tooltip(message: 'error saving profile', child: Text("Failed"));
return Tooltip(message: strings.profileFailedSaveMessage, child: Text(strings.failed));
}

if (state is ProfileFailedStart) {
return Tooltip(message: state.reason ?? 'No Reason Provided', child: const Text("Failed"));
return Tooltip(message: state.reason ?? strings.profileFailedUnknownMessage, child: Text(strings.failed));
}

if (state is ProfileStarting && state.status != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:npt_flutter/features/profile/profile.dart';
import 'package:npt_flutter/features/features.dart';
import 'package:npt_flutter/features/profile_form/widgets/profile_relay_at_sign_text_field.dart';
import 'package:npt_flutter/styles/sizes.dart';
import 'package:npt_flutter/util/relay.dart';
import 'package:npt_flutter/widgets/custom_container.dart';

class ProfileRelayQuickButtons extends StatelessWidget {
Expand Down Expand Up @@ -44,29 +43,29 @@ class ProfileRelayQuickButtons extends StatelessWidget {
scrollDirection: Axis.horizontal,
controller: controller,
children: [
...RelayUtil.getRelayDisplayNameMap(context).entries.map(
(e) => Padding(
padding: const EdgeInsets.only(right: Sizes.p10),
child: CustomContainer.foreground(
key: Key(e.key),
child: SizedBox(
width: Sizes.p200,
height: Sizes.p50,
child: RadioListTile(
title: Text(e.value),
value: e.key,
groupValue: relayAtsign,
onChanged: (value) {
var bloc = context.read<ProfileBloc>();
bloc.add(ProfileEditEvent(
profile: (bloc.state as ProfileLoadedState).profile.copyWith(relayAtsign: value),
));
},
),
),
...RelayOptions.values.map(
(e) => Padding(
padding: const EdgeInsets.only(right: Sizes.p10),
child: CustomContainer.foreground(
key: Key(e.name),
child: SizedBox(
width: Sizes.p200,
height: Sizes.p50,
child: RadioListTile(
title: Text(e.regions),
value: e.relayAtsign,
groupValue: relayAtsign,
onChanged: (value) {
var bloc = context.read<ProfileBloc>();
bloc.add(ProfileEditEvent(
profile: (bloc.state as ProfileLoadedState).profile.copyWith(relayAtsign: value),
));
},
),
),
),
),
),
const ProfileRelayAtSignTextField(),
],
),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:npt_flutter/app.dart';
import 'package:npt_flutter/util/language.dart';

part 'settings.g.dart';

Expand All @@ -15,16 +16,6 @@ enum PreferredViewLayout {
final String displayName;
}

@JsonEnum()
enum Language {
@JsonValue("en")
english,
@JsonValue("es")
spanish,
@JsonValue("pt-br")
portuguese,
}

@JsonSerializable()
class Settings extends Loggable {
final String relayAtsign;
Expand All @@ -38,11 +29,11 @@ class Settings extends Loggable {
final Language language;

const Settings({
this.relayAtsign = '@rv_am',
required this.relayAtsign,
required this.overrideRelay,
required this.viewLayout,
this.darkMode = false,
this.language = Language.english,
required this.language,
});

Settings copyWith({
Expand Down Expand Up @@ -83,28 +74,37 @@ class Settings extends Loggable {
}
}

extension LanguageExtension on Language {
Locale get locale {
enum RelayOptions {
am,
eu,
ap,
}

extension RelayOptionsExtension on RelayOptions {
String get relayAtsign {
switch (this) {
case Language.english:
return const Locale('en');
case Language.spanish:
return const Locale('es');
case Language.portuguese:
return const Locale('pt', 'BR');
case RelayOptions.am:
return '@rv_am';
case RelayOptions.eu:
return '@rv_eu';
case RelayOptions.ap:
return '@rv_ap';
}
}

String get displayName {
String get regions {
final strings = AppLocalizations.of(App.navState.currentContext!)!;
switch (this) {
case Language.english:
return 'English';
case Language.spanish:
return 'Español';
case Language.portuguese:
return 'Português';
case RelayOptions.am:
return strings.americas;
case RelayOptions.eu:
return strings.europe;
case RelayOptions.ap:
return strings.asiaPacific;
}
}
}



// ['English', 'Spanish', 'Br portuguese', 'Mandarin', 'Cantonese']
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import 'dart:convert';
import 'dart:io';

import 'package:at_client_mobile/at_client_mobile.dart';
import 'package:flutter/material.dart';
import 'package:npt_flutter/constants.dart';
import 'package:npt_flutter/features/settings/settings.dart';
import 'package:npt_flutter/util/language.dart';

class SettingsRepository {
const SettingsRepository();
AtKey get settingsAtKey => AtKey.self('settings', namespace: Constants.namespace).build();

Settings get defaultSettings => const Settings(
Settings get defaultSettings => Settings(
relayAtsign: RelayOptions.am.relayAtsign,
viewLayout: PreferredViewLayout.minimal,
overrideRelay: false,
// set the default language to the device's language
language: LanguageUtil.getLanguageFromLocale(Locale(Platform.localeName)),
);

Future<Settings?> getSettings() async {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

import '../../../styles/app_color.dart';
import '../../../styles/sizes.dart';
Expand All @@ -11,6 +12,7 @@ class ContactListTile extends StatelessWidget {
Widget build(BuildContext context) {
SizeConfig().init();
final contactRepo = ContactsService.getInstance();
final strings = AppLocalizations.of(context)!;

final bodyMedium = Theme.of(context).textTheme.bodyMedium!;
final bodySmall = Theme.of(context).textTheme.bodySmall!;
Expand Down Expand Up @@ -45,12 +47,12 @@ class ContactListTile extends StatelessWidget {
),
);
} else {
return const ListTile(
leading: CircleAvatar(
return ListTile(
leading: const CircleAvatar(
child: Icon(Icons.person),
),
title: Text('No Name'),
subtitle: Text('No Atsign'),
title: Text(strings.noName),
subtitle: Text(strings.noAtsign),
);
}
}));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:npt_flutter/features/settings/settings.dart';
import 'package:npt_flutter/util/language.dart';
import 'package:npt_flutter/widgets/spinner.dart';

class SettingsLanguageSelector extends StatelessWidget {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,25 @@ class SettingsOverrideRelaySwitch extends StatelessWidget {
return null;
}, builder: (context, overrideRelay) {
if (overrideRelay == null) return const Center(child: Spinner());
return Row(
children: [
Checkbox(
value: overrideRelay,
onChanged: (value) {
var bloc = context.read<SettingsBloc>();
bloc.add(SettingsEditEvent(
settings: (bloc.state as SettingsLoadedState).settings.copyWith(overrideRelay: value),
save: true,
));
},
),
Text(
strings.overrideAllProfile,
),
],
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
Checkbox(
value: overrideRelay,
onChanged: (value) {
var bloc = context.read<SettingsBloc>();
bloc.add(SettingsEditEvent(
settings: (bloc.state as SettingsLoadedState).settings.copyWith(overrideRelay: value),
save: true,
));
},
),
Text(
strings.overrideAllProfile,
),
],
),
);
});
}
Expand Down
Loading

0 comments on commit 326533b

Please sign in to comment.