Hello I'm tonakainohana.
I want to localize CupertinoDatePicker widget.
And I tryed to do that to refefence this question.
And I finally Got it. Like this.I succeeded to localize this Widget in Japanese.
But, When I check this appearance in Android Emurator and Chrome, It failed to change language. It appeared to default language.
please look pictures below.
I don't get any point of that. Does anyone know why in these devices localization doesn't work well?
This is part of my code below.
import 'dart:math' as math;
import 'package:flutter/cupertino.dart';
import 'package:intl/intl.dart' as intl;
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'JapaneseCupertinoLocalizations.dart' as jcl;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
DefaultCupertinoLocalizations.delegate,
jcl.JapaneseCupertinoLocalizations.delegate,
],
supportedLocales: [
const Locale('en', 'US'),
const Locale('ja', 'JP'),
],
//locale: Locale('ja', 'JP'), //It supporsed to OK to commentout
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Page0(),
);
}
}
/* ━━━━━━━━━━━ 関数 ━━━━━━━━━━━ */
//CupertinoTimePicker
Widget _buildBottomPicker(Widget picker) {
return Container(
height:216,
padding:const EdgeInsets.only(top:6.0),
color: CupertinoColors.white,
child:DefaultTextStyle(
style:const TextStyle(
color:CupertinoColors.black,
fontSize:22.0,
),
child: GestureDetector(
onTap:(){},
child:SafeArea(
top:false,
child: picker,
)
)
),
);
}
Route _createNextRoute(Widget classRtnWidget) {
return PageRouteBuilder(
pageBuilder: (context, animation,secondaryAnimation) => classRtnWidget,
transitionsBuilder: (context, animation, secondaryAnimation,child){
var begin = Offset(1.0,0.0);
var end = Offset.zero;
var curve = Curves.ease;
var tween = Tween(begin: begin, end: end).chain(CurveTween(curve:curve));
return SlideTransition(
position: animation.drive(tween),
child: child,
);
},
);
}
/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
/* ━━━━━━━━━ StatefulWidget ━━━━━━━━━━━━ */
class Page0 extends StatefulWidget {
@override
Page0State createState() => Page0State();
}
class Page2 extends StatefulWidget {
@override
Page2State createState() => Page2State();
}
/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
/* ━━━━━━━━━━━━━ State ━━━━━━━━━━━━━━ */
class Page0State extends State<Page0> {
final Object heroTag = "next";
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child:Text('アンケートにご協力ください'),
),
floatingActionButton: FloatingActionButton(
heroTag: heroTag,
child: Icon(Icons.forward),
onPressed: (){
Navigator.push(
context,
_createNextRoute(Page2())
);
}
),
);
}
}
class Page2State extends State<Page2> {
final Object heroTagNext = "next";
final Object heroTagBefore = "before";
DateTime _date = DateTime.now();
@override
void initState(){
super.initState();
initializeDateFormat();
}
Future<void> initializeDateFormat() async{
await initializeDateFormatting("ja_JP", null);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body:
Stack(
children:<Widget> [
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width:1000,
height:100,
child: Row(
children: <Widget>[
CupertinoButton(
child:Text('来所時間'),
onPressed: () {
//DateFormat debug
print( intl.DateFormat.yMMMEd('ja').format(_date));
showCupertinoModalPopup<void>(
context: context,
builder: (BuildContext context) {
return _buildBottomPicker(
CupertinoDatePicker(
mode: CupertinoDatePickerMode.dateAndTime,
initialDateTime: _date,
onDateTimeChanged: (DateTime newDateTime) {
setState(() {
_date = newDateTime;
});
})
);
},
);
},
),
// Text('DateFormat.yMMMEd().format($_date)'),
]
),
),
],
),
Positioned(
//右の次へボタン
bottom:50,
right: 50,
child:FloatingActionButton(
heroTag: heroTagNext,
child: Icon(Icons.forward),
onPressed: () {
Navigator.push(
context,
_createNextRoute(Page3()) //Actually Page3 Class Exists
);
},
),
),
Positioned(
//左の前へボタン
bottom: 50,
left:50,
child: FloatingActionButton(
heroTag: heroTagBefore,
child:Icon(
Icons.forward,
textDirection: TextDirection.rtl,
),
onPressed:(){
Navigator.pop(context);
},
),
),
],
),
);
}
}
/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
↓JapaneseCupertinoLocalizations.dart is imported main.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
class _CupertinoLocalizationDelegate extends LocalizationsDelegate<CupertinoLocalizations> {
const _CupertinoLocalizationDelegate();
@override
bool isSupported(Locale locale) => locale.languageCode == 'ja';
@override
Future<CupertinoLocalizations> load(Locale locale)=> JapaneseCupertinoLocalizations.load(locale);
@override
bool shouldReload( _CupertinoLocalizationDelegate old) => false;
@override
String toString() => 'DefaultCupertinoLocalizations.delegate(ja_JP)';
}
class JapaneseCupertinoLocalizations implements CupertinoLocalizations{
const JapaneseCupertinoLocalizations();
static const List<String> _shortWeekdays = <String>[
'(月)',
'(火)',
'(水)',
'(木)',
'(金)',
'(土)',
'(日)',
];
static const List<String> _shortMonths = <String> [
'1月',
'2月',
'3月',
'4月',
'5月',
'6月',
'7月',
'8月',
'9月',
'10月',
'11月',
'12月',
];
static const List<String> _months = <String>[
'1月',
'2月',
'3月',
'4月',
'5月',
'6月',
'7月',
'8月',
'9月',
'10月',
'11月',
'12月',
];
@override
String datePickerYear(int yearIndex) => yearIndex.toString();
@override
String datePickerMonth(int monthIndex) => _months[monthIndex -1];
@override
String datePickerDayOfMonth(int dayIndex) => dayIndex.toString();
@override
String datePickerHour(int hour) => hour.toString();
@override
String datePickerHourSemanticsLabel( int hour) => hour.toString() + "時";
@override
String datePickerMinute(int minute) => minute.toString().padLeft(2, '0');
@override
String datePickerMinuteSemanticsLabel( int minute) {
if(minute == 1)
return '1 分';
return minute.toString() + '分';
}
@override
String datePickerMediumDate(DateTime date) {
return
'${_shortMonths[date.month - DateTime.january]} '
'${date.day.toString().padRight(2)+ '日'}'
'${_shortWeekdays[date.weekday - DateTime.monday] } ';
}
@override
DatePickerDateOrder get datePickerDateOrder => DatePickerDateOrder.mdy;
@override
DatePickerDateTimeOrder get datePickerDateTimeOrder => DatePickerDateTimeOrder.date_time_dayPeriod;
@override
String get anteMeridiemAbbreviation => '午前';
@override
String get postMeridiemAbbreviation => '午後';
@override
String get alertDialogLabel => 'Info';
@override
String timerPickerHour(int hour ) => hour.toString();
@override
String timerPickerMinute(int minute) => minute.toString();
@override
String timerPickerSecond(int second) => second.toString();
@override
String timerPickerHourLabel(int hour) => hour == 1 ? '時' : '時'; //勉強のため参考の書式のまま
@override
String timerPickerMinuteLabel(int minute) => '分';
@override
String timerPickerSecondLabel(int second) => '秒';
@override
String get cutButtonLabel => 'カット';
@override
String get copyButtonLabel => 'コピー';
@override
String get pasteButtonLabel => 'ペースト';
@override
String get selectAllButtonLabel => '選択';
@override
String get todayLabel => '今日'; //参考サイトにはなかったが、参照しないとエラーが出るので独自で追加
/// Creates an object that provides US English resource values for the
/// cupertino library widgets.
///
/// The [locale] parameter is ignored.
/// localeパラメーターは無視されている。
/// This method is typically used to create a [LocalizationsDelegate].
/// LocalizationsDelegateによってこのメソッド(load)は呼ばれる
static Future<CupertinoLocalizations> load(Locale locale) {
return SynchronousFuture<CupertinoLocalizations>(const JapaneseCupertinoLocalizations());
}
/// A [LocalizationsDelegate] that uses [DefaultCupertinoLocalizations.load]
/// to create an instance of this class.
static const LocalizationsDelegate<CupertinoLocalizations> delegate = _CupertinoLocalizationDelegate();
}
Thank you for your reading my question and your good advice.