1

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.

enter image description here

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.

enter image description here

enter image description here

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.

1 Answers1

0

Now I got it! Just remove comment out and write locale.

'''

  localizationsDelegates: [
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    DefaultCupertinoLocalizations.delegate,
    jcl.JapaneseCupertinoLocalizations.delegate,
  ],

  supportedLocales: [
    const Locale('en', 'US'),
    const Locale('ja', 'JP'),
  ],
  //locale: Locale('ja', 'JP'),    // ×
  locale: Locale('ja', 'JP'),      // 〇 It needs write locale.

'''