Skip to content

Commit

Permalink
localization
Browse files Browse the repository at this point in the history
  • Loading branch information
chooyan-eng committed Mar 4, 2024
1 parent f3b7ca9 commit 09ce571
Show file tree
Hide file tree
Showing 20 changed files with 225 additions and 95 deletions.
3 changes: 3 additions & 0 deletions l10n.yaml
@@ -0,0 +1,3 @@
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
39 changes: 39 additions & 0 deletions lib/l10n/app_en.arb
@@ -0,0 +1,39 @@
{
"@@locale": "en",
"@helloWorld": {
"description": "The conventional newborn programmer greeting"
},
"name": "chooyan",
"occupation": "Freelance Flutter App Developer",
"imageFile": "me_photo.jpeg",
"social": "@tsuyoshi_chujo",
"slideTitle": "Build Dynamic Slides with Flutter",
"slideSubTitle": "02.29.2024 @Flutter Night #2",
"introduction": "About me",
"myJob": "Freelance Flutter App Developer. Also working as a technical advisor of Flutter",
"ossActivities": "Publishing Flutter packages and writing articles",
"slideDeckWithFlutter": "Build Slide Decks with Flutter",
"aboutFlutterDeck": "flutter_deck",
"aboutFlutterDeck11": "",
"aboutFlutterDeck12": "Enables us to build ",
"aboutFlutterDeck13": "Flutter apps behaving like a slide deck",
"aboutFlutterDeck21": "Because it's a Flutter app, ",
"aboutFlutterDeck22": "slide decks can do whatever we usually do on Flutter",
"aboutFlutterDeck3": "This slide deck is also a Flutter app 😊",
"buildingScreen": "Screenshot of making this slide deck",
"case1Title": "case 1: Counter App",
"case2Title": "case 2: Explaining AsyncValue's Behavior",
"stateOfAsyncValue": "State of AsyncValue",
"forceError": "Force Error",
"case3Title": "case 3: Introducing crop_your_image",
"cropYourImageDemo": "Demo of crop_your_image",
"croppedImageDescription": "Cropped image comes below",
"conclusion": "Conclusion",
"conclusion11": "flutter_deck enable us to ",
"conclusion12": "run Flutter app in our slide decks ",
"conclusion13": "that is valuable for demo or visual explanation.",
"conclusion2": "Any knowledge or tools for Flutter apps are also available.",
"conclusion3": "No need to spend more time to build a slide deck comparing to using Keynote. It's a Flutter app!",
"conclusion4": "Slide decks can be published as Flutter web on GitHub pages.",
"thanks": "Enjoy making slide decks with Flutter!"
}
36 changes: 36 additions & 0 deletions lib/l10n/app_ja.arb
@@ -0,0 +1,36 @@
{
"@@locale": "ja",
"name": "ちゅーやん(中條 剛)",
"occupation": "フリーランス Flutter アプリ開発者",
"imageFile": "me.jpg",
"social": "@chooyan_i18n",
"slideTitle": "Flutterで作る「動的」な登壇資料",
"slideSubTitle": "2024.02.29 @Flutter Night #2",
"introduction": "自己紹介",
"myJob": "フリーランスの Flutter アプリ開発者です。講師や技術顧問もやってます。",
"ossActivities": "Zenn や hashnode への記事の投稿やパッケージ開発などもやっています。",
"slideDeckWithFlutter": "Flutter アプリで登壇資料を作る",
"aboutFlutterDeck": "flutter_deck とは",
"aboutFlutterDeck11": "「スライドみたいに動く Flutter アプリ」",
"aboutFlutterDeck12": "を作ってくれるパッケージ。",
"aboutFlutterDeck13": "",
"aboutFlutterDeck21": "Flutter アプリなので、",
"aboutFlutterDeck22": "Flutter でできることはなんでもできる!",
"aboutFlutterDeck3": "この資料も flutter_deck で作っています 😊",
"buildingScreen": "このページの作成画面",
"case1Title": "活用例その1: カウンターアプリ",
"case2Title": "活用例その2: AsyncValueの挙動解説",
"stateOfAsyncValue": "AsyncValueの状態",
"forceError": "強制エラー",
"case3Title": "活用例その3: crop_your_image の紹介",
"cropYourImageDemo": "crop_your_image のデモ",
"croppedImageDescription": "切り抜いた画像は ↓ のボックスに表示されます",
"conclusion": "まとめ",
"conclusion11": "flutter_deck は",
"conclusion12": "「スライドの中でコードを動かせる」",
"conclusion13": "ので、内部状態を可視化したりデモを入れたりするのに最適",
"conclusion2": "Flutter アプリ開発における工夫がそのまま使える(バージョン管理など)",
"conclusion3": "資料作成も意外と時間がかからない。この資料で3, 4時間くらい。",
"conclusion4": "資料の公開は Flutter Web で GitHub Pages へ",
"thanks": "ご清聴ありがとうございました"
}
78 changes: 44 additions & 34 deletions lib/main.dart
Expand Up @@ -11,6 +11,7 @@ import 'package:flutter_night_2/slide/end/end_slide.dart';
import 'package:flutter_night_2/slide/introduction/introduction_slide.dart';
import 'package:flutter_night_2/slide/title/title_slide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

void main() {
runApp(const ProviderScope(child: MainApp()));
Expand All @@ -21,45 +22,54 @@ class MainApp extends StatelessWidget {

@override
Widget build(BuildContext context) {
return FlutterDeckApp(
configuration: const FlutterDeckConfiguration(
controls: FlutterDeckControlsConfiguration(
shortcuts: FlutterDeckShortcutsConfiguration(
nextSlide: SingleActivator(LogicalKeyboardKey.enter),
previousSlide: SingleActivator(LogicalKeyboardKey.backspace),
return MaterialApp(
debugShowCheckedModeBanner: false,
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: Builder(
builder: (c) => FlutterDeckApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
configuration: const FlutterDeckConfiguration(
controls: FlutterDeckControlsConfiguration(
shortcuts: FlutterDeckShortcutsConfiguration(
nextSlide: SingleActivator(LogicalKeyboardKey.enter),
previousSlide: SingleActivator(LogicalKeyboardKey.backspace),
),
),
),
),
),
lightTheme: FlutterDeckThemeData(
theme: ThemeData(
scaffoldBackgroundColor: Colors.white,
textTheme: const TextTheme(
headlineLarge: TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
lightTheme: FlutterDeckThemeData(
theme: ThemeData(
scaffoldBackgroundColor: Colors.white,
textTheme: const TextTheme(
headlineLarge: TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
),
bodyLarge: TextStyle(fontSize: 28),
bodySmall: TextStyle(fontSize: 18),
),
),
bodyLarge: TextStyle(fontSize: 28),
bodySmall: TextStyle(fontSize: 18),
),
slides: const [
TitleSlide(),
IntroductionSlide(),
AboutSlide(),
AboutDeckSlide(),
CounterAppSlide(),
AsyncValueSlide(),
CropYourImageSlide(),
ConclusionSlide(),
EndSlide(),
],
speakerInfo: FlutterDeckSpeakerInfo(
name: AppLocalizations.of(c)!.name,
description: AppLocalizations.of(c)!.occupation,
imagePath: 'assets/images/${AppLocalizations.of(c)!.imageFile}',
socialHandle: AppLocalizations.of(c)!.social,
),
),
),
slides: const [
TitleSlide(),
IntroductionSlide(),
AboutSlide(),
AboutDeckSlide(),
CounterAppSlide(),
AsyncValueSlide(),
CropYourImageSlide(),
ConclusionSlide(),
EndSlide(),
],
speakerInfo: const FlutterDeckSpeakerInfo(
name: 'ちゅーやん(中條 剛)',
description: 'フリーランス Flutter アプリ開発者',
imagePath: 'assets/images/me.jpg',
socialHandle: '@chooyan_i18n',
),
);
}
}
3 changes: 2 additions & 1 deletion lib/slide/about/about_slide.dart
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_deck/flutter_deck.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class AboutSlide extends FlutterDeckSlideWidget {
const AboutSlide()
Expand All @@ -15,7 +16,7 @@ class AboutSlide extends FlutterDeckSlideWidget {
FlutterDeckSlide build(BuildContext context) {
return FlutterDeckSlide.bigFact(
title: 'flutter_deck',
subtitle: 'Flutter アプリで登壇資料を作る',
subtitle: AppLocalizations.of(context)!.slideDeckWithFlutter,
);
}
}
32 changes: 22 additions & 10 deletions lib/slide/about_deck/about_deck_page.dart
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_night_2/component/components.dart';
import 'package:gap/gap.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class AboutDeckPage extends StatelessWidget {
const AboutDeckPage({super.key});
Expand All @@ -13,31 +14,42 @@ class AboutDeckPage extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const RichParagraph(
RichParagraph(
[
TextSpan(
text: '「スライドみたいに動く Flutter アプリ」',
style: TextStyle(
text: AppLocalizations.of(context)!.aboutFlutterDeck11,
style: const TextStyle(
fontWeight: FontWeight.w700,
color: Colors.blue,
),
),
TextSpan(
text: AppLocalizations.of(context)!.aboutFlutterDeck12,
),
TextSpan(
text: AppLocalizations.of(context)!.aboutFlutterDeck13,
style: const TextStyle(
fontWeight: FontWeight.w700, color: Colors.blue),
),
TextSpan(text: 'を作ってくれるパッケージ。'),
],
),
const Gap(32),
const RichParagraph(
RichParagraph(
[
TextSpan(text: 'Flutter アプリなので、'),
TextSpan(
text: 'Flutter でできることはなんでもできる!',
style: TextStyle(
text: AppLocalizations.of(context)!.aboutFlutterDeck21,
),
TextSpan(
text: AppLocalizations.of(context)!.aboutFlutterDeck22,
style: const TextStyle(
fontWeight: FontWeight.w700,
color: Colors.blue,
),
),
],
),
const Gap(32),
const Paragraph('この資料も flutter_deck で作っています 😊'),
Paragraph(AppLocalizations.of(context)!.aboutFlutterDeck3),
const Gap(32),
Expanded(
child: Center(
Expand All @@ -47,7 +59,7 @@ class AboutDeckPage extends StatelessWidget {
child: Image.asset('assets/images/coding_image.png'),
),
const Gap(8),
const Paragraph('このページの作成画面'),
Paragraph(AppLocalizations.of(context)!.buildingScreen),
],
),
),
Expand Down
5 changes: 3 additions & 2 deletions lib/slide/about_deck/about_deck_slide.dart
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_deck/flutter_deck.dart';
import 'package:flutter_night_2/slide/about_deck/about_deck_page.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class AboutDeckSlide extends FlutterDeckSlideWidget {
const AboutDeckSlide()
Expand All @@ -17,8 +18,8 @@ class AboutDeckSlide extends FlutterDeckSlideWidget {
return FlutterDeckSlide.template(
contentBuilder: (_) => const AboutDeckPage(),
headerBuilder: (context) {
return const FlutterDeckHeader(
title: 'flutter_deck とは',
return FlutterDeckHeader(
title: AppLocalizations.of(context)!.aboutFlutterDeck,
);
},
);
Expand Down
5 changes: 3 additions & 2 deletions lib/slide/asyncvalue/asyncvalue_page.dart
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter_night_2/slide/asyncvalue/todo_list.dart';
import 'package:flutter_night_2/slide/asyncvalue/todo_list_app.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:gap/gap.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class AsyncValuePage extends StatelessWidget {
const AsyncValuePage({super.key});
Expand Down Expand Up @@ -47,7 +48,7 @@ class _AsyncValueState extends ConsumerWidget {
child: Column(
children: [
const Gap(60),
const Label('AsyncValueの状態'),
Label(AppLocalizations.of(context)!.stateOfAsyncValue),
const Gap(120),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
Expand Down Expand Up @@ -84,7 +85,7 @@ class _AsyncValueState extends ConsumerWidget {
Row(
mainAxisSize: MainAxisSize.min,
children: [
const Paragraph('強制エラー'),
Paragraph(AppLocalizations.of(context)!.forceError),
const Gap(16),
Switch(
value: forceError,
Expand Down
5 changes: 3 additions & 2 deletions lib/slide/asyncvalue/asyncvalue_slide.dart
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_deck/flutter_deck.dart';
import 'package:flutter_night_2/slide/asyncvalue/asyncvalue_page.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class AsyncValueSlide extends FlutterDeckSlideWidget {
const AsyncValueSlide()
Expand All @@ -17,8 +18,8 @@ class AsyncValueSlide extends FlutterDeckSlideWidget {
return FlutterDeckSlide.template(
contentBuilder: (_) => const AsyncValuePage(),
headerBuilder: (context) {
return const FlutterDeckHeader(
title: '活用例その2: AsyncValueの挙動解説',
return FlutterDeckHeader(
title: AppLocalizations.of(context)!.case2Title,
);
},
);
Expand Down
19 changes: 11 additions & 8 deletions lib/slide/conclusion/conclusion_page.dart
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_night_2/component/components.dart';
import 'package:gap/gap.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class ConclusionPage extends StatelessWidget {
const ConclusionPage({super.key});
Expand All @@ -13,26 +14,28 @@ class ConclusionPage extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Label('flutter_deck は'),
Label(AppLocalizations.of(context)!.conclusion11),
const Gap(60),
const RichParagraph(
RichParagraph(
[
TextSpan(
text: '「スライドの中でコードを動かせる」',
style: TextStyle(
text: AppLocalizations.of(context)!.conclusion12,
style: const TextStyle(
fontWeight: FontWeight.w700,
color: Colors.blue,
),
),
TextSpan(text: 'ので、内部状態を可視化したりデモを入れたりするのに最適'),
TextSpan(
text: AppLocalizations.of(context)!.conclusion13,
),
],
),
const Gap(32),
const Paragraph('Flutter アプリ開発における工夫がそのまま使える(バージョン管理など)'),
Paragraph(AppLocalizations.of(context)!.conclusion2),
const Gap(32),
const Paragraph('資料作成も意外と時間がかからない。この資料で3, 4時間くらい。'),
Paragraph(AppLocalizations.of(context)!.conclusion3),
const Gap(32),
const Paragraph('資料の公開は Flutter Web で GitHub Pages へ(たぶん)'),
Paragraph(AppLocalizations.of(context)!.conclusion4),
const Gap(60),
Expanded(
child: Align(
Expand Down
5 changes: 3 additions & 2 deletions lib/slide/conclusion/conclusion_slide.dart
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_deck/flutter_deck.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_night_2/slide/conclusion/conclusion_page.dart';

class ConclusionSlide extends FlutterDeckSlideWidget {
Expand All @@ -17,8 +18,8 @@ class ConclusionSlide extends FlutterDeckSlideWidget {
return FlutterDeckSlide.template(
contentBuilder: (_) => const ConclusionPage(),
headerBuilder: (context) {
return const FlutterDeckHeader(
title: 'まとめ',
return FlutterDeckHeader(
title: AppLocalizations.of(context)!.conclusion,
);
},
);
Expand Down

0 comments on commit 09ce571

Please sign in to comment.