Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add localization #2748

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
10 changes: 10 additions & 0 deletions pkgs/sketch_pad/lib/l10n/de.arb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"@@locale": "de",
"@@x-template": "en.arb",
"newPad": "Neu",
"samples": "Beispiele",
"installSdk": "SDK installieren",
"privacyNotice": "Datenschutzerklärung",
"feedback": "Feedback",
"channelSelection": "{channelName} channel"
}
1 change: 1 addition & 0 deletions pkgs/sketch_pad/lib/l10n/de.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[0,"de","zZF8nm5r",0,null,[" channel",[0,0]],"Feedback","SDK installieren","Neu","Datenschutzerklärung","Beispiele"]
mosuem marked this conversation as resolved.
Show resolved Hide resolved
34 changes: 34 additions & 0 deletions pkgs/sketch_pad/lib/l10n/en.arb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"@@locale": "en",
"newPad": "New",
"@newPad": {
"description": "Button to create a new pad"
},
"samples": "Samples",
"@samples": {
"description": "Button to show a list of all samples"
},
"installSdk": "Install SDK",
"@installSdk": {
"description": "Button to follow external link to webpage helping on installing the Dart SDK"
},
"privacyNotice": "Privacy Notice",
"@privacyNotice": {
"description": "Button to show privacy notice on external web page"
},
"feedback": "Feedback",
"@feedback": {
"description": "Button to give feedback on external web page"
},
"channelSelection": "{channelName} channel",
"@channelSelection": {
"description": "Text field describing the Dart SDK channel selected by the user",
"placeholders": {
"channelName": {
"type": "String",
"description": "The name of the channel",
"example": "Stable"
}
}
}
}
48 changes: 48 additions & 0 deletions pkgs/sketch_pad/lib/l10n/en.flutter.g.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Generated by package:flutter_messages
mosuem marked this conversation as resolved.
Show resolved Hide resolved

import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:messages/package_intl_object.dart';

import 'en.g.dart';

class MessagesLocalizations {
static Iterable<LocalizationsDelegate<dynamic>> localizationsDelegates = [
delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
];

static LocalizationsDelegate<Messages> delegate =
MessagesLocalizationsDelegate();

static List<Locale> get supportedLocales {
return Messages.knownLocales.map((e) {
final split = e.split('_');
final code = split.length > 1 ? split[1] : null;
return Locale(split.first, code);
}).toList();
}

static Messages? of(BuildContext context) =>
Localizations.of<Messages>(context, Messages);
}

class MessagesLocalizationsDelegate extends LocalizationsDelegate<Messages> {
mosuem marked this conversation as resolved.
Show resolved Hide resolved
@override
bool isSupported(Locale locale) =>
Messages.knownLocales.contains(locale.toString());

@override
Future<Messages> load(Locale locale) async {
await messages.loadLocale(locale.toString());
return messages;
}

@override
bool shouldReload(LocalizationsDelegate<Messages> old) => false;
}

Messages messages = Messages(rootBundle.loadString, const OldIntlObject());
mosuem marked this conversation as resolved.
Show resolved Hide resolved
66 changes: 66 additions & 0 deletions pkgs/sketch_pad/lib/l10n/en.g.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Generated by package:messages_builder
mosuem marked this conversation as resolved.
Show resolved Hide resolved

import 'package:messages/messages_json.dart';

class Messages {
Messages(
this._fileLoader,
this.intlObject,
);

final Future<String> Function(String id) _fileLoader;

String _currentLocale = 'en';

final Map<String, MessageList> _messages = {};

static const carbs = {
mosuem marked this conversation as resolved.
Show resolved Hide resolved
'en': ('lib/l10n/en.json', '/JmmZcLq'),
'de': ('lib/l10n/de.json', 'zZF8nm5r')
};

IntlObject intlObject;

String get currentLocale => _currentLocale;

MessageList get _currentMessages => _messages[currentLocale]!;

static Iterable<String> get knownLocales => carbs.keys;

Future<void> loadLocale(String locale) async {
if (!_messages.containsKey(locale)) {
final info = carbs[locale];
final carb = info?.$1;
if (carb == null) {
throw ArgumentError('Locale $locale is not in $knownLocales');
}
final data = await _fileLoader(carb);
final messageList = MessageListJson.fromString(data, intlObject);
if (messageList.preamble.hash != info?.$2) {
throw ArgumentError('''
Messages file for locale $locale has different hash "${messageList.preamble.hash}" than generated code "${info?.$2}".''');
}
_messages[locale] = messageList;
}
_currentLocale = locale;
}

void loadAllLocales() {
for (final locale in knownLocales) {
loadLocale(locale);
}
}

String channelSelection(String channelName) =>
_currentMessages.generateStringAtIndex(0, [channelName]);

String get feedback => _currentMessages.generateStringAtIndex(1, []);

String get installSdk => _currentMessages.generateStringAtIndex(2, []);

String get newPad => _currentMessages.generateStringAtIndex(3, []);

String get privacyNotice => _currentMessages.generateStringAtIndex(4, []);

String get samples => _currentMessages.generateStringAtIndex(5, []);
}
1 change: 1 addition & 0 deletions pkgs/sketch_pad/lib/l10n/en.json
mosuem marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[0,"en","/JmmZcLq",0,null,[" channel",[0,0]],"Feedback","Install SDK","New","Privacy Notice","Samples"]
40 changes: 25 additions & 15 deletions pkgs/sketch_pad/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import 'editor/editor.dart';
import 'execution/execution.dart';
import 'extensions.dart';
import 'keys.dart' as keys;
import 'l10n/en.flutter.g.dart';
import 'model.dart';
import 'problems.dart';
import 'samples.g.dart';
Expand Down Expand Up @@ -137,6 +138,14 @@ class _DartPadAppState extends State<DartPadApp> {
routerConfig: router,
debugShowCheckedModeBanner: false,
themeMode: themeMode,
localizationsDelegates: [...MessagesLocalizations.localizationsDelegates],
supportedLocales: const [
Locale('en'), // English
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for this PR, but it may be nice to have some CI checks that this list matches the arbs files available, and the list of json files in the flutter assets section.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how Flutter currently handles this matching between supportedLocales and actually existing .arb files. @HansMuller?

Locale('es'), // Spanish
Locale('de'), // German
Locale('ar'), // Arabic
],
locale: const Locale('de'), //DO_NOT_SUBMIT: Uncomment this to test UI
mosuem marked this conversation as resolved.
Show resolved Hide resolved
theme: ThemeData(
useMaterial3: true,
colorScheme:
Expand Down Expand Up @@ -282,11 +291,11 @@ class _DartPadMainPageState extends State<DartPadMainPage> {
Uri.parse('https://docs.flutter.dev/get-started/install'),
);
},
child: const Row(
child: Row(
children: [
Text('Install SDK'),
SizedBox(width: denseSpacing),
Icon(Icons.launch, size: 18),
Text(MessagesLocalizations.of(context)!.installSdk),
mosuem marked this conversation as resolved.
Show resolved Hide resolved
const SizedBox(width: denseSpacing),
const Icon(Icons.launch, size: 18),
],
),
),
Expand Down Expand Up @@ -585,11 +594,11 @@ class StatusLineWidget extends StatelessWidget {
const url = 'https://dart.dev/tools/dartpad/privacy';
url_launcher.launchUrl(Uri.parse(url));
},
child: const Row(
child: Row(
children: [
Text('Privacy notice'),
SizedBox(width: denseSpacing),
Icon(Icons.launch, size: 16),
Text(MessagesLocalizations.of(context)!.privacyNotice),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When to prefer MessageLocalizations.of(context) over context.messageLocalizations?

const SizedBox(width: denseSpacing),
const Icon(Icons.launch, size: 16),
],
),
),
Expand All @@ -599,11 +608,11 @@ class StatusLineWidget extends StatelessWidget {
const url = 'https://github.com/dart-lang/dart-pad/issues';
url_launcher.launchUrl(Uri.parse(url));
},
child: const Row(
child: Row(
children: [
Text('Feedback'),
SizedBox(width: denseSpacing),
Icon(Icons.launch, size: 16),
Text(MessagesLocalizations.of(context)!.feedback),
const SizedBox(width: denseSpacing),
const Icon(Icons.launch, size: 16),
],
),
),
Expand Down Expand Up @@ -673,7 +682,7 @@ class NewSnippetWidget extends StatelessWidget {
height: toolbarItemHeight,
child: TextButton.icon(
icon: const Icon(Icons.add_circle),
label: const Text('New'),
label: Text(MessagesLocalizations.of(context)!.newPad),
onPressed: () async {
final selection =
await _showMenu(context, calculatePopupMenuPosition(context));
Expand Down Expand Up @@ -728,7 +737,7 @@ class ListSamplesWidget extends StatelessWidget {
height: toolbarItemHeight,
child: TextButton.icon(
icon: const Icon(Icons.playlist_add_outlined),
label: const Text('Samples'),
label: Text(MessagesLocalizations.of(context)!.samples),
onPressed: () async {
final selection =
await _showMenu(context, calculatePopupMenuPosition(context));
Expand Down Expand Up @@ -797,7 +806,8 @@ class SelectChannelWidget extends StatelessWidget {
icon: const Icon(Icons.tune, size: smallIconSize),
label: Container(
constraints: const BoxConstraints(minWidth: 95),
child: Text('${value.displayName} channel'),
child: Text(MessagesLocalizations.of(context)!
.channelSelection(value.displayName)),
),
onPressed: () async {
final selection = await _showMenu(
Expand Down
11 changes: 11 additions & 0 deletions pkgs/sketch_pad/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,39 @@ dependencies:
dartpad_shared: any
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
fluttering_phrases: ^1.0.0
go_router: ^12.1.0
http: any
intl: any
mosuem marked this conversation as resolved.
Show resolved Hide resolved
json_annotation: ^4.8.1
pointer_interceptor: ^0.9.0
provider: ^6.0.0
split_view: ^3.2.0
url_launcher: any
url_strategy: any
vtable: ^0.4.0
messages: ^0.1.0
mosuem marked this conversation as resolved.
Show resolved Hide resolved

dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.0
test: any
build_runner: 2.4.6
mosuem marked this conversation as resolved.
Show resolved Hide resolved
build_runner_core: 7.2.10
flutter_messages: ^0.1.0
messages_serializer: ^0.1.0
messages_builder: ^0.1.0

flutter:
uses-material-design: true
assets:
- assets/dart_logo_128.png
- assets/flutter_logo_192.png
- lib/l10n/en.json
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for this PR, but we should add some docs to the repo about how to contribute a new localization; this will be a good way to get more people involved.

- lib/l10n/de.json

dependency_overrides:
dartpad_shared:
Expand Down