ソースコード source code

下記アプリの主要なソースコードを公開しています。アプリ開発の参考になれば幸いです。

画像等が別途必要ですので下記情報のみでアプリが完成するものではありません。 アプリは少しずつ機能拡張していますのでストア公開されているアプリと内容が異なる場合があります。 コードはコピーして自由にお使いいただけます。ただし著作権は放棄しておりませんので全部の再掲載はご遠慮ください。部分的に再掲載したり、改変して再掲載するのは構いません。 自身のアプリ作成の参考として個人使用・商用問わず自由にお使いいただけます。 コード記述のお手本を示すものではありません。ミニアプリですので変数名などさほど気遣いしていない部分も有りますし間違いも有るかと思いますので参考程度にお考え下さい。 他の賢者の皆様が公開されているコードを参考にした箇所も含まれます。Flutter開発の熟練者が書いたコードではありません。 エンジニア向け技術情報共有サービスではありませんので説明は省いています。 GitHubなどへの公開は予定しておりません。

下記コードの最終ビルド日: 2023-11-19

pubspec.yaml

name: wattconversion
description: "Watt Conversion"
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev

# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.1+2

environment:
  sdk: '>=3.3.0-152.0.dev <4.0.0'

# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.6
  package_info_plus: ^5.0.1
  shared_preferences: ^2.0.17
  flutter_localizations:    #多言語ライブラリの本体    # .arbファイルを更新したら flutter gen-l10n
    sdk: flutter
  intl: ^0.18.1     #多言語やフォーマッタなどの関連ライブラリ
  google_mobile_ads: ^3.1.0
  just_audio: ^0.9.35

dev_dependencies:
  flutter_test:
    sdk: flutter

  flutter_launcher_icons: ^0.13.1    #flutter pub run flutter_launcher_icons
  flutter_native_splash: ^2.3.6     #flutter pub run flutter_native_splash:create

  # The "flutter_lints" package below contains a set of recommended lints to
  # encourage good coding practices. The lint set provided by the package is
  # activated in the `analysis_options.yaml` file located at the root of your
  # package. See that file for information about deactivating specific lint
  # rules and activating additional ones.
  flutter_lints: ^3.0.1

# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

flutter_launcher_icons:
  android: "launcher_icon"
  ios: true
  image_path: "assets/icon/icon.png"
  adaptive_icon_background: "assets/icon/icon_back.png"
  adaptive_icon_foreground: "assets/icon/icon_fore.png"

flutter_native_splash:
  color: '#3dbdd0'
  image: 'assets/image/splash.png'
  color_dark: '#3dbdd0'
  image_dark: 'assets/image/splash.png'
  fullscreen: true
  android_12:
    icon_background_color: '#3dbdd0'
    image: 'assets/image/splash.png'
    icon_background_color_dark: '#3dbdd0'
    image_dark: 'assets/image/splash.png'

# The following section is specific to Flutter packages.
flutter:
  generate: true    #自動生成フラグの有効化

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  # assets:
  #   - images/a_dot_burr.jpeg
  #   - images/a_dot_ham.jpeg
  assets:
    - assets/image/
    - assets/sound/

  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.dev/assets-and-images/#resolution-aware

  # For details regarding adding assets from package dependencies, see
  # https://flutter.dev/assets-and-images/#from-packages

  # To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  # example:
  # fonts:
  #   - family: Schyler
  #     fonts:
  #       - asset: fonts/Schyler-Regular.ttf
  #       - asset: fonts/Schyler-Italic.ttf
  #         style: italic
  #   - family: Trajan Pro
  #     fonts:
  #       - asset: fonts/TrajanPro.ttf
  #       - asset: fonts/TrajanPro_Bold.ttf
  #         weight: 700
  #
  # For details regarding fonts from package dependencies,
  # see https://flutter.dev/custom-fonts/#from-packages

lib/ad_mob.dart

///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2023-02-06
///
library;

import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'dart:io';

class AdMob {
  late BannerAd _adMobBanner;
  bool _isAdMob = false;
  AdMob() { //constructor
    String adBannerUnitId = '';
    if (!kIsWeb && Platform.isAndroid) {
      //adBannerUnitId = 'ca-app-pub-3940256099942544/6300978111';  //test
      adBannerUnitId = 'ca-app-pub-0000000000000000/0000000000';
      _isAdMob = true;
    } else if (!kIsWeb && Platform.isIOS) {
      //adBannerUnitId = 'ca-app-pub-3940256099942544/6300978111';  //test
      adBannerUnitId = 'ca-app-pub-0000000000000000/0000000000';
      _isAdMob = true;
    }
    if (_isAdMob) {
      _adMobBanner = BannerAd(
        adUnitId: adBannerUnitId,
        size: AdSize.banner,
        request: const AdRequest(),
        listener: const BannerAdListener(),
      );
    }
  }
  void load() {
    if (_isAdMob) {
      _adMobBanner.load();
    }
  }
  void dispose() {
    if (_isAdMob) {
      _adMobBanner.dispose();
    }
  }
  Widget getAdBannerWidget() {
    if (_isAdMob) {
      return Container(
        alignment: Alignment.center,
        width: _adMobBanner.size.width.toDouble(),
        height: _adMobBanner.size.height.toDouble(),
        child: AdWidget(ad: _adMobBanner),
      );
    } else {
      return Container();
    }
  }
  double getAdBannerHeight() {
    if (_isAdMob) {
      return _adMobBanner.size.height.toDouble();
    } else {
      return 150;  //for web
    }
  }
}

lib/audio_play.dart

///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2023-01-27
///
library;

import 'package:just_audio/just_audio.dart';

import 'package:wattconversion/const_value.dart';

class AudioPlay {
  //音を重ねて連続再生できるようにインスタンスを用意しておき、順繰りに使う。
  static final List<AudioPlayer> _player01 = [
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),  //6個
  ];
  int _player01Ptr = 0;

  double _soundVolume = 0.0;

  //constructor
  AudioPlay() {
    constructor();
  }
  void constructor() async {
    for (int i = 0; i < _player01.length; i++) {
      await _player01[i].setVolume(0);
      await _player01[i].setAsset(ConstValue.audioHiyoko[i]);
    }
    playZero();
  }
  void dispose() {
    for (int i = 0; i < _player01.length; i++) {
      _player01[i].dispose();
    }
  }
  //getter
  double get soundVolume {
    return _soundVolume;
  }
  //setter
  set soundVolume(double vol) {
    _soundVolume = vol;
  }
  //最初に音が鳴らないのを回避する方法
  void playZero() async {
    AudioPlayer ap = AudioPlayer();
    await ap.setAsset(ConstValue.audioZero);
    await ap.load();
    await ap.play();
  }
  //
  void play01() async {
    if (_soundVolume == 0) {
      return;
    }
    _player01Ptr += 1;
    if (_player01Ptr >= _player01.length) {
      _player01Ptr = 0;
    }
    await _player01[_player01Ptr].setVolume(_soundVolume);
    await _player01[_player01Ptr].pause();
    await _player01[_player01Ptr].seek(Duration.zero);
    await _player01[_player01Ptr].play();
  }
}

lib/const_value.dart

///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2023-10-15
///
library;

import 'package:flutter/material.dart';

class ConstValue {
  //pref
  static const String prefLanguageCode = 'languageCode';
  static const String prefShowBackImage = 'showBackImage';
  static const String prefSoundVolume = 'soundVolume';
  static const String prefWattFrom = 'wattFrom';
  static const String prefWattTo = 'wattTo';
  static const String prefMinute = 'minute';
  static const String prefSecond = 'second';
  static const List<String> imageBacks = [
    'assets/image/kitchen001.webp',
    'assets/image/kitchen002.webp',
    'assets/image/kitchen003.webp',
    'assets/image/kitchen004.webp',
    'assets/image/kitchen005.webp',
    'assets/image/kitchen006.webp',
    'assets/image/kitchen007.webp',
    'assets/image/kitchen008.webp',
    'assets/image/kitchen009.webp',
    'assets/image/kitchen010.webp',
    'assets/image/kitchen011.webp',
    'assets/image/kitchen012.webp',
    'assets/image/kitchen013.webp',
    'assets/image/kitchen014.webp',
    'assets/image/kitchen015.webp',
    'assets/image/kitchen016.webp',
    'assets/image/kitchen017.webp',
    'assets/image/kitchen018.webp',
    'assets/image/kitchen019.webp',
    'assets/image/kitchen020.webp',
    'assets/image/kitchen021.webp',
    'assets/image/kitchen022.webp',
    'assets/image/kitchen023.webp',
    'assets/image/kitchen024.webp',
    'assets/image/kitchen025.webp',
    'assets/image/kitchen026.webp',
    'assets/image/kitchen027.webp',
    'assets/image/kitchen028.webp',
    'assets/image/kitchen029.webp',
    'assets/image/kitchen030.webp',
    'assets/image/kitchen031.webp',
    'assets/image/kitchen032.webp',
    'assets/image/kitchen033.webp',
    'assets/image/kitchen034.webp',
    'assets/image/kitchen035.webp',
    'assets/image/kitchen036.webp',
    'assets/image/kitchen037.webp',
    'assets/image/kitchen038.webp',
    'assets/image/kitchen039.webp',
    'assets/image/kitchen040.webp',
    'assets/image/kitchen041.webp',
    'assets/image/kitchen042.webp',
    'assets/image/kitchen043.webp',
    'assets/image/kitchen044.webp',
    'assets/image/kitchen045.webp',
    'assets/image/kitchen046.webp',
    'assets/image/kitchen047.webp',
    'assets/image/kitchen048.webp',
    'assets/image/kitchen049.webp',
    'assets/image/kitchen050.webp',
    'assets/image/kitchen051.webp',
    'assets/image/kitchen052.webp',
    'assets/image/kitchen053.webp',
    'assets/image/kitchen054.webp',
    'assets/image/kitchen055.webp',
    'assets/image/kitchen056.webp',
    'assets/image/kitchen057.webp',
    'assets/image/kitchen058.webp',
    'assets/image/kitchen059.webp',
    'assets/image/kitchen060.webp',
    'assets/image/kitchen061.webp',
    'assets/image/kitchen062.webp',
    'assets/image/kitchen063.webp',
    'assets/image/kitchen064.webp',
    'assets/image/kitchen065.webp',
    'assets/image/kitchen066.webp',
    'assets/image/kitchen067.webp',
    'assets/image/kitchen068.webp',
    'assets/image/kitchen069.webp',
    'assets/image/kitchen070.webp',
    'assets/image/kitchen071.webp',
    'assets/image/kitchen072.webp',
    'assets/image/kitchen073.webp',
    'assets/image/kitchen074.webp',
    'assets/image/kitchen075.webp',
    'assets/image/kitchen076.webp',
    'assets/image/kitchen077.webp',
    'assets/image/kitchen078.webp',
    'assets/image/kitchen079.webp',
    'assets/image/kitchen080.webp',
    'assets/image/kitchen081.webp',
    'assets/image/kitchen082.webp',
    'assets/image/kitchen083.webp',
    'assets/image/kitchen084.webp',
    'assets/image/kitchen085.webp',
    'assets/image/kitchen086.webp',
    'assets/image/kitchen087.webp',
    'assets/image/kitchen088.webp',
    'assets/image/kitchen089.webp',
    'assets/image/kitchen090.webp',
    'assets/image/kitchen091.webp',
    'assets/image/kitchen092.webp',
    'assets/image/kitchen093.webp',
    'assets/image/kitchen094.webp',
    'assets/image/kitchen095.webp',
    'assets/image/kitchen096.webp',
    'assets/image/kitchen097.webp',
    'assets/image/kitchen098.webp',
    'assets/image/kitchen099.webp',
    'assets/image/kitchen100.webp',
    'assets/image/kitchen101.webp',
    'assets/image/kitchen102.webp',
    'assets/image/kitchen103.webp',
    'assets/image/kitchen104.webp',
    'assets/image/kitchen105.webp',
    'assets/image/kitchen106.webp',
    'assets/image/kitchen107.webp',
    'assets/image/kitchen108.webp',
    'assets/image/kitchen109.webp',
    'assets/image/kitchen110.webp',
    'assets/image/kitchen111.webp',
    'assets/image/kitchen112.webp',
    'assets/image/kitchen113.webp',
    'assets/image/kitchen114.webp',
    'assets/image/kitchen115.webp',
    'assets/image/kitchen116.webp',
    'assets/image/kitchen117.webp',
    'assets/image/kitchen118.webp',
    'assets/image/kitchen119.webp',
    'assets/image/kitchen120.webp',
    'assets/image/kitchen121.webp',
    'assets/image/kitchen122.webp',
    'assets/image/kitchen123.webp',
    'assets/image/kitchen124.webp',
    'assets/image/kitchen125.webp',
    'assets/image/kitchen126.webp',
    'assets/image/kitchen127.webp',
    'assets/image/kitchen128.webp',
    'assets/image/kitchen129.webp',
    'assets/image/kitchen130.webp',
    'assets/image/kitchen131.webp',
    'assets/image/kitchen132.webp',
    'assets/image/kitchen133.webp',
    'assets/image/kitchen134.webp',
    'assets/image/kitchen135.webp',
    'assets/image/kitchen136.webp',
    'assets/image/kitchen137.webp',
    'assets/image/kitchen138.webp',
    'assets/image/kitchen139.webp',
    'assets/image/kitchen140.webp',
    'assets/image/kitchen141.webp',
    'assets/image/kitchen142.webp',
    'assets/image/kitchen143.webp',
    'assets/image/kitchen144.webp',
    'assets/image/kitchen145.webp',
    'assets/image/kitchen146.webp',
    'assets/image/kitchen147.webp',
    'assets/image/kitchen148.webp',
    'assets/image/kitchen149.webp',
    'assets/image/kitchen150.webp',
    'assets/image/kitchen151.webp',
    'assets/image/kitchen152.webp',
    'assets/image/kitchen153.webp',
    'assets/image/kitchen154.webp',
    'assets/image/kitchen155.webp',
    'assets/image/kitchen156.webp',
    'assets/image/kitchen157.webp',
    'assets/image/kitchen158.webp',
    'assets/image/kitchen159.webp',
    'assets/image/kitchen160.webp',
    'assets/image/kitchen161.webp',
    'assets/image/kitchen162.webp',
    'assets/image/kitchen163.webp',
    'assets/image/kitchen164.webp',
    'assets/image/kitchen165.webp',
    'assets/image/kitchen166.webp',
    'assets/image/kitchen167.webp',
    'assets/image/kitchen168.webp',
    'assets/image/kitchen169.webp',
    'assets/image/kitchen170.webp',
    'assets/image/kitchen171.webp',
    'assets/image/kitchen172.webp',
    'assets/image/kitchen173.webp',
    'assets/image/kitchen174.webp',
    'assets/image/kitchen175.webp',
    'assets/image/kitchen176.webp',
    'assets/image/kitchen177.webp',
    'assets/image/kitchen178.webp',
    'assets/image/kitchen179.webp',
    'assets/image/kitchen180.webp',
    'assets/image/kitchen181.webp',
    'assets/image/kitchen182.webp',
    'assets/image/kitchen183.webp',
    'assets/image/kitchen184.webp',
    'assets/image/kitchen185.webp',
    'assets/image/kitchen186.webp',
    'assets/image/kitchen187.webp',
    'assets/image/kitchen188.webp',
    'assets/image/kitchen189.webp',
    'assets/image/kitchen190.webp',
    'assets/image/kitchen191.webp',
    'assets/image/kitchen192.webp',
    'assets/image/kitchen193.webp',
    'assets/image/kitchen194.webp',
    'assets/image/kitchen195.webp',
    'assets/image/kitchen196.webp',
    'assets/image/kitchen197.webp',
    'assets/image/kitchen198.webp',
    'assets/image/kitchen199.webp',
    'assets/image/kitchen200.webp',
  ];
  //color
  static const Color colorMainHeader = Color.fromRGBO(81,123,235,0.8);
  static const Color colorSettingHeader = Color.fromRGBO(81,123,235,0.8);
  static const Color colorMainBack = Color.fromRGBO(81,123,235,0.6);
  static const Color colorMainUiBack = Color.fromRGBO(255,255,255,0.6);
  static const Color colorMainUiBack2 = Color.fromRGBO(255,255,255,0.8);
  static const Color colorMainUiActiveColorFrom = Color.fromRGBO(255,0,50,1);
  static const Color colorMainUiActiveColorTo = Color.fromRGBO(60,50,255,1);
  static const Color colorSettingUiActiveColor = Color.fromRGBO(81,123,235,1);
  static const Color colorUiInactiveColor = Color.fromRGBO(50,50,50,1);
  //sound
  static const String audioZero = 'assets/sound/zero.wav';    //無音1秒
  static const List<String> audioHiyoko = [
    'assets/sound/hiyoko1.wav',
    'assets/sound/hiyoko2.wav',
    'assets/sound/hiyoko3.wav',
    'assets/sound/hiyoko4.wav',
    'assets/sound/hiyoko5.wav',
    'assets/sound/hiyoko6.wav',
  ];
  //string
  static const Map<String,String> languageCode = {
    'en': 'English',
    'bg': 'български език',
    'cs': 'Čeština',
    'da': 'dansk',
    'de': 'Deutsch',
    'el': 'Ελληνικά',
    'es': 'Español',
    'et': 'eesti keel',
    'fi': 'Suomen kieli',
    'fr': 'Français',
    'hu': 'magyar nyelv',
    'it': 'Italiano',
    'ja': '日本語',
    'lt': 'lietuvių kalba',
    'lv': 'Latviešu',
    'nl': 'Nederlands',
    'pl': 'Polski',
    'pt': 'Português',
    'ro': 'limba română',
    'ru': 'русский',
    'sk': 'Slovenčina',
    'sv': 'svenska',
    'th': 'ภาษาไทย',
    'zh': '中文',
  };

}

lib/empty.dart

lib/language_state.dart

///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2023-01-27
///
library;

import 'package:wattconversion/preferences.dart';

class LanguageState {

  static String _languageCode = 'en';

  //言語コードを記録
  static Future<void> setLanguageCode(String str) async {
    _languageCode = str;
    await Preferences.setLanguageCode(_languageCode);
  }
  //言語コードを返す
  static Future<String> getLanguageCode() async {
    _languageCode = await Preferences.getLanguageCode() ?? 'en';
    return _languageCode;
  }

}

lib/main.dart

///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2023-10-02
///
library;

import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart' if (dart.library.html) 'empty.dart';
import 'package:flutter/foundation.dart' show kIsWeb;

import 'package:wattconversion/const_value.dart';
import 'package:wattconversion/language_state.dart';
import 'package:wattconversion/version_state.dart';
import 'package:wattconversion/setting.dart';
import 'package:wattconversion/ad_mob.dart';
import 'package:wattconversion/page_state.dart';
import 'package:wattconversion/preferences.dart';
import 'package:wattconversion/audio_play.dart';

void main() {
  runApp(const MainApp());
}

class MainApp extends StatefulWidget {    //statefulに変更して言語変更に対応
  const MainApp({super.key});
  @override
  State<MainApp> createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> {
  Locale localeLanguage = const Locale('en');
  @override
  Widget build(BuildContext context) {
    if (kIsWeb == false) {
      MobileAds.instance.initialize();
    }
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      localizationsDelegates: AppLocalizations.localizationsDelegates,   //多言語化
      supportedLocales: AppLocalizations.supportedLocales,  //自動で言語リストを生成
      locale: localeLanguage,
      home: const MainHomePage(),
    );
  }
}

class MainHomePage extends StatefulWidget {
  const MainHomePage({super.key});
  @override
  State<MainHomePage> createState() => _MainHomePageState();
}

class _MainHomePageState extends State<MainHomePage> with SingleTickerProviderStateMixin {
  final AdMob _adMob = AdMob(); //広告表示
  final AudioPlay _audioPlay = AudioPlay(); //効果音
  late AnimationController _animationController;
  late Animation<double> _opacityAnimation;
  bool _showBackImage = true;
  int _backImageNumber = 0;
  int _lastBackImageNumber = 0;
  int _wattFrom = 600;
  int _wattTo = 500;
  int _minute = 5;
  int _second = 0;
  double _screenWidth = 0;

  //アプリのバージョン取得
  void _getVersion() async {
    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    setState(() {
      VersionState.versionSave(packageInfo.version);
    });
  }
  //言語準備
  void _getCurrentLocale() async {
    Locale locale = Locale(await LanguageState.getLanguageCode());
    if (mounted) {  //Widgetが存在する。Widgetが存在しない時の実行によるエラーを回避する為。
      context.findAncestorStateOfType<_MainAppState>()!
        ..localeLanguage = locale
        ..setState(() {});
    }
  }
  //ページ起動開始時に一度だけ呼ばれる
  @override
  void initState() {
    super.initState();
    _getVersion();
    _getCurrentLocale();
    LanguageState.getLanguageCode();
    _adMob.load();
    _audioPlay.playZero();
    final int subSecond = (DateTime.now()).millisecondsSinceEpoch ~/ 100;
    _backImageNumber = subSecond % ConstValue.imageBacks.length;
    //background animation
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 500),
    );
    _opacityAnimation = Tween<double>(begin: 0, end: 1).animate(_animationController);
    _animationController.addListener(() {
      setState(() {});
    });
    _backImageChange();
    //
    (() async {
      await Preferences.initial();
      _showBackImage = Preferences.showBackImage;
      _audioPlay.soundVolume = Preferences.soundVolume;
      _wattFrom = Preferences.wattFrom;
      _wattTo = Preferences.wattTo;
      _minute = Preferences.minute;
      _second = Preferences.second;
      setState(() {});
    })();
  }
  //ページ終了時に一度だけ呼ばれる
  @override
  void dispose() {
    PageState.setCurrentPage('');
    _adMob.dispose();
    super.dispose();
  }
  //画面全体
  @override
  Widget build(BuildContext context) {
    _screenWidth = MediaQuery.of(context).size.width;
    return GestureDetector(
      onTap: () {
        _audioPlay.play01();
        _backImageChange();
      },
      child: Container(
        decoration: const BoxDecoration(
          color: ConstValue.colorMainBack,
        ),
        child: Container(
          decoration: _decoration2(),
          child: Container(
            decoration: _decoration1(),
            child: Scaffold(
              backgroundColor: Colors.transparent, //ここは透明
              appBar: AppBar(
                backgroundColor: ConstValue.colorMainHeader,
                //タイトル表示
                title: Text(AppLocalizations.of(context)!.title,
                  style: const TextStyle(
                    color: Colors.white,
                    fontSize: 12.0,
                  )
                ),
                //設定ボタン
                actions: <Widget>[
                  TextButton(
                    onPressed: () async {
                      bool? ret = await Navigator.of(context).push(
                        MaterialPageRoute<bool>(builder:(context) => const SettingPage()),
                      );
                      //awaitで呼び出しているので、settingから戻ったら以下が実行される。
                      if (ret!) { //設定で適用だった場合
                        _getCurrentLocale();
                        _showBackImage = Preferences.showBackImage;
                        _audioPlay.soundVolume = Preferences.soundVolume;
                        setState(() {});
                      }
                    },
                    child: Text(
                      AppLocalizations.of(context)!.setting,
                      style: const TextStyle(
                        color: Colors.white,
                        fontSize: 12.0,
                      )
                    )
                  )
                ]
              ),
              body: SafeArea(
                child: Column(children: [
                  Expanded(
                    child: SingleChildScrollView(
                      child: Padding(
                        padding: const EdgeInsets.only(top: 5, left: 5, right: 5, bottom: 100),
                        child: Column(children: [
                          _content(),
                        ])
                      )
                    )
                  ),
                  //広告
                  Padding(
                    padding: const EdgeInsets.only(top: 10, left: 0, right: 0, bottom: 0),
                    child: SizedBox(
                      width: double.infinity,
                      child: _adMob.getAdBannerWidget(),
                    )
                  )
                ])
              )
            )
          )
        )
      )
    );
  }
  //背景画像前側
  Decoration _decoration1() {
    if (_showBackImage) {
      return BoxDecoration(
        image: DecorationImage(
          image: AssetImage(ConstValue.imageBacks[_backImageNumber]),
          fit: BoxFit.cover,
          colorFilter: ColorFilter.mode(
            Colors.black.withOpacity(_opacityAnimation.value),
            BlendMode.dstATop,
          ),
        )
      );
    } else {
      return const BoxDecoration();
    }
  }
  //背景画像後ろ側
  Decoration _decoration2() {
    if (_showBackImage) {
      return BoxDecoration(
        image: DecorationImage(
          image: AssetImage(ConstValue.imageBacks[_lastBackImageNumber]),
          fit: BoxFit.cover,
        ),
      );
    } else {
      return const BoxDecoration();
    }
  }
  void _backImageChange() {
    final int subSecond = (DateTime.now()).millisecondsSinceEpoch ~/ 100;
    _backImageNumber = subSecond % ConstValue.imageBacks.length;
    _animationController.forward();
    Future.delayed(const Duration(milliseconds: 600), () {
      _lastBackImageNumber = _backImageNumber;
      _animationController.reverse();
    });
  }
  Widget _content() {
    final int sec = ((_minute * 60 + _second) / _wattTo * _wattFrom).toInt();
    final int answerMinute = (sec / 60).floor();
    final int answerSecond = sec % 60;
    return Column(children:[
      _widgetWattFrom(),
      _widgetMinute(),
      _widgetSecond(),
      const SizedBox(height:5),
      _widgetWattTo(),
      const SizedBox(height:5),
      Container(
        color: ConstValue.colorMainUiBack2,
        child: Padding(
        padding: const EdgeInsets.only(top: 5, left: 0, right: 0, bottom: 5),
          child: Column(children:[
            Row(children: [
              const Spacer(),
              Text('${AppLocalizations.of(context)!.specified} ${_wattFrom}W ${_minute} ${AppLocalizations.of(context)!.minute} ${_second} ${AppLocalizations.of(context)!.second}',
                style: const TextStyle(
                  color: ConstValue.colorMainUiActiveColorFrom,
                  fontSize: 15
                )
              ),
              const Spacer(),
            ]),
            Row(children: [
              const Spacer(),
              Text('${AppLocalizations.of(context)!.conversion} ${_wattTo}W ${answerMinute} ${AppLocalizations.of(context)!.minute} ${answerSecond} ${AppLocalizations.of(context)!.second}',
                style: const TextStyle(
                  color: ConstValue.colorMainUiActiveColorTo,
                  fontSize:15
                )
              ),
              const Spacer(),
            ])
          ])
        )
      )
    ]);
  }
  Widget _widgetWattFrom() {
    return Container(
      color: ConstValue.colorMainUiBack,
      child: Column(children:[
        Padding(
          padding: const EdgeInsets.only(top: 5, left: 10, right: 0, bottom: 0),
          child: Row(children: [
            Text(AppLocalizations.of(context)!.wattFrom,style: const TextStyle(fontSize: 12)),
            const Spacer(),
          ])
        ),
        Padding(
          padding: const EdgeInsets.only(top: 0, left: 10, right: 0, bottom: 0),
          child: Row(children: <Widget>[
            Container(
              color: Colors.white,
              child: SizedBox(
                width: 35,
                child: Text(_wattFrom.toString(),textAlign: TextAlign.center),
              )
            ),
            Expanded(
              child: Slider(
                value: _wattFrom.toDouble(),
                min: 300,
                max: 1800,
                divisions: 15,
                onChanged: (double value) {
                  setState(() {
                    _wattFrom = value.toInt();
                    Preferences.setWattFrom(_wattFrom);
                  });
                },
                activeColor: ConstValue.colorMainUiActiveColorFrom,
                inactiveColor: ConstValue.colorUiInactiveColor,
              )
            )
          ])
        )
      ])
    );
  }
  Widget _widgetMinute() {
    return Container(
      color: ConstValue.colorMainUiBack,
      child: Column(children:[
        Padding(
          padding: const EdgeInsets.only(top: 5, left: 10, right: 0, bottom: 0),
          child: Row(children: [
            Text(AppLocalizations.of(context)!.fromMinute,style: const TextStyle(fontSize: 12)),
            const Spacer(),
          ])
        ),
        Padding(
          padding: const EdgeInsets.only(top: 0, left: 10, right: 0, bottom: 0),
          child: Row(children: <Widget>[
            Container(
              color: Colors.white,
              child: SizedBox(
                width: 35,
                child: Text(_minute.toString(),textAlign: TextAlign.center),
              )
            ),
            Expanded(
              child: Slider(
                value: _minute.toDouble(),
                min: 1,
                max: 30,
                divisions: 29,
                onChanged: (double value) {
                  setState(() {
                    _minute = value.toInt();
                    Preferences.setMinute(_minute);
                  });
                },
                activeColor: ConstValue.colorMainUiActiveColorFrom,
                inactiveColor: ConstValue.colorUiInactiveColor,
              )
            )
          ])
        )
      ])
    );
  }
  Widget _widgetSecond() {
    return Container(
      color: ConstValue.colorMainUiBack,
      child: Column(children:[
        Padding(
          padding: const EdgeInsets.only(top: 5, left: 10, right: 0, bottom: 0),
          child: Row(children: [
            Text(AppLocalizations.of(context)!.fromSecond,style: const TextStyle(fontSize: 12)),
            const Spacer(),
          ])
        ),
        Padding(
          padding: const EdgeInsets.only(top: 0, left: 10, right: 0, bottom: 0),
          child: Row(children: <Widget>[
            Container(
              color: Colors.white,
              child: SizedBox(
                width: 35,
                child: Text(_second.toString(),textAlign: TextAlign.center),
              )
            ),
            Expanded(
              child: Slider(
                value: _second.toDouble(),
                min: 0,
                max: 50,
                divisions: 5,
                onChanged: (double value) {
                  setState(() {
                    _second = value.toInt();
                    Preferences.setMinute(_second);
                  });
                },
                activeColor: ConstValue.colorMainUiActiveColorFrom,
                inactiveColor: ConstValue.colorUiInactiveColor,
              )
            )
          ])
        )
      ])
    );
  }
  Widget _widgetWattTo() {
    return Container(
      color: ConstValue.colorMainUiBack,
      child: Column(children:[
        Padding(
          padding: const EdgeInsets.only(top: 5, left: 10, right: 0, bottom: 0),
          child: Row(children: [
            Text(AppLocalizations.of(context)!.wattTo,style: const TextStyle(fontSize: 12)),
            const Spacer(),
          ])
        ),
        Padding(
          padding: const EdgeInsets.only(top: 0, left: 10, right: 0, bottom: 0),
          child: Row(children: <Widget>[
            Container(
              color: Colors.white,
              child: SizedBox(
                width: 35,
                child: Text(_wattTo.toString(),textAlign: TextAlign.center),
              )
            ),
            Expanded(
              child: Slider(
                value: _wattTo.toDouble(),
                min: 300,
                max: 1800,
                divisions: 15,
                onChanged: (double value) {
                  setState(() {
                    _wattTo = value.toInt();
                    Preferences.setWattTo(_wattTo);
                  });
                },
                activeColor: ConstValue.colorMainUiActiveColorTo,
                inactiveColor: ConstValue.colorUiInactiveColor,
              )
            )
          ])
        ),
      ])
    );
  }

}

lib/main.dart.old20231204 (旧バージョン。記録として残す)

///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2023-10-02
///
library;

import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart' if (dart.library.html) 'empty.dart';
import 'package:flutter/foundation.dart' show kIsWeb;

import 'package:wattconversion/const_value.dart';
import 'package:wattconversion/language_state.dart';
import 'package:wattconversion/version_state.dart';
import 'package:wattconversion/setting.dart';
import 'package:wattconversion/ad_mob.dart';
import 'package:wattconversion/page_state.dart';
import 'package:wattconversion/preferences.dart';
import 'package:wattconversion/audio_play.dart';

void main() {
  runApp(const MainApp());
}

class MainApp extends StatefulWidget {    //statefulに変更して言語変更に対応
  const MainApp({super.key});
  @override
  State<MainApp> createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> {
  Locale localeLanguage = const Locale('en');
  @override
  Widget build(BuildContext context) {
    if (kIsWeb == false) {
      MobileAds.instance.initialize();
    }
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      localizationsDelegates: AppLocalizations.localizationsDelegates,   //多言語化
      supportedLocales: AppLocalizations.supportedLocales,  //自動で言語リストを生成
      locale: localeLanguage,
      home: const MainHomePage(),
    );
  }
}

class MainHomePage extends StatefulWidget {
  const MainHomePage({super.key});
  @override
  State<MainHomePage> createState() => _MainHomePageState();
}

class _MainHomePageState extends State<MainHomePage> with SingleTickerProviderStateMixin {
  final AdMob _adMob = AdMob(); //広告表示
  final AudioPlay _audioPlay = AudioPlay(); //効果音
  late AnimationController _animationController;
  late Animation<double> _opacityAnimation;
  bool _showBackImage = true;
  int _backImageNumber = 0;
  int _lastBackImageNumber = 0;
  int _wattFrom = 600;
  int _wattTo = 500;
  int _minute = 5;
  int _second = 0;
  double _screenWidth = 0;

  //アプリのバージョン取得
  void _getVersion() async {
    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    setState(() {
      VersionState.versionSave(packageInfo.version);
    });
  }
  //言語準備
  void _getCurrentLocale() async {
    Locale locale = Locale(await LanguageState.getLanguageCode());
    if (mounted) {  //Widgetが存在する。Widgetが存在しない時の実行によるエラーを回避する為。
      context.findAncestorStateOfType<_MainAppState>()!
        ..localeLanguage = locale
        ..setState(() {});
    }
  }
  //ページ起動開始時に一度だけ呼ばれる
  @override
  void initState() {
    super.initState();
    _getVersion();
    _getCurrentLocale();
    LanguageState.getLanguageCode();
    _adMob.load();
    _audioPlay.playZero();
    final int subSecond = (DateTime.now()).millisecondsSinceEpoch ~/ 100;
    _backImageNumber = subSecond % ConstValue.imageBacks.length;
    //background animation
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 500),
    );
    _opacityAnimation = Tween<double>(begin: 0, end: 1).animate(_animationController);
    _animationController.addListener(() {
      setState(() {});
    });
    _backImageChange();
    //
    (() async {
      await Preferences.initial();
      _showBackImage = Preferences.showBackImage;
      _audioPlay.soundVolume = Preferences.soundVolume;
      _wattFrom = Preferences.wattFrom;
      _wattTo = Preferences.wattTo;
      _minute = Preferences.minute;
      _second = Preferences.second;
      setState(() {});
    })();
  }
  //ページ終了時に一度だけ呼ばれる
  @override
  void dispose() {
    PageState.setCurrentPage('');
    _adMob.dispose();
    super.dispose();
  }
  //画面全体
  @override
  Widget build(BuildContext context) {
    _screenWidth = MediaQuery.of(context).size.width;
    return GestureDetector(
      onTap: () {
        _audioPlay.play01();
        _backImageChange();
      },
      child: Container(
        decoration: const BoxDecoration(
          color: ConstValue.colorBack,
        ),
        child: Container(
          decoration: _decoration2(),
          child: Container(
            decoration: _decoration1(),
            child: Scaffold(
              backgroundColor: Colors.transparent, //ここは透明
              appBar: AppBar(
                backgroundColor: ConstValue.colorHeader,
                //タイトル表示
                title: Text(AppLocalizations.of(context)!.title,
                  style: const TextStyle(
                    color: Colors.white,
                    fontSize: 12.0,
                  )
                ),
                //設定ボタン
                actions: <Widget>[
                  TextButton(
                    onPressed: () async {
                      bool? ret = await Navigator.of(context).push(
                        MaterialPageRoute<bool>(builder:(context) => const SettingPage()),
                      );
                      //awaitで呼び出しているので、settingから戻ったら以下が実行される。
                      if (ret!) { //設定で適用だった場合
                        _getCurrentLocale();
                        _showBackImage = Preferences.showBackImage;
                        _audioPlay.soundVolume = Preferences.soundVolume;
                        setState(() {});
                      }
                    },
                    child: Text(
                      AppLocalizations.of(context)!.setting,
                      style: const TextStyle(
                        color: Colors.white,
                        fontSize: 12.0,
                      )
                    )
                  )
                ]
              ),
              body: SafeArea(
                child: Column(children: [
                  Expanded(
                    child: SingleChildScrollView(
                      child: Padding(
                        padding: const EdgeInsets.only(top: 5, left: 5, right: 5, bottom: 100),
                        child: Column(children: [
                          _content(),
                        ])
                      )
                    )
                  ),
                  //広告
                  Padding(
                    padding: const EdgeInsets.only(top: 10, left: 0, right: 0, bottom: 0),
                    child: SizedBox(
                      width: double.infinity,
                      child: _adMob.getAdBannerWidget(),
                    )
                  )
                ])
              )
            )
          )
        )
      )
    );
  }
  //背景画像前側
  Decoration _decoration1() {
    if (_showBackImage) {
      return BoxDecoration(
          image: DecorationImage(
            image: AssetImage(ConstValue.imageBacks[_backImageNumber]),
            fit: BoxFit.cover,
            colorFilter: ColorFilter.mode(
              Colors.black.withOpacity(_opacityAnimation.value),
              BlendMode.dstATop,
            ),
          )
      );
    } else {
      return const BoxDecoration();
    }
  }
  //背景画像後ろ側
  Decoration _decoration2() {
    if (_showBackImage) {
      return BoxDecoration(
        image: DecorationImage(
          image: AssetImage(ConstValue.imageBacks[_lastBackImageNumber]),
          fit: BoxFit.cover,
        ),
      );
    } else {
      return const BoxDecoration();
    }
  }
  void _backImageChange() {
    final int subSecond = (DateTime.now()).millisecondsSinceEpoch ~/ 100;
    _backImageNumber = subSecond % ConstValue.imageBacks.length;
    _animationController.forward();
    Future.delayed(const Duration(milliseconds: 600), () {
      _lastBackImageNumber = _backImageNumber;
      _animationController.reverse();
    });
  }
  Widget _content() {
    final int sec = ((_minute * 60 + _second) / _wattTo * _wattFrom).toInt();
    final int answerMinute = (sec / 60).floor();
    final int answerSecond = sec % 60;
    return Column(children:[
      Container(
        color: ConstValue.colorForeUiBack1,
        child: Row(children: [
          const SizedBox(width:5),
          Text(AppLocalizations.of(context)!.wattFrom,
            style: const TextStyle(
              color: ConstValue.colorForeFrom,
              fontSize: 12
            )
          ),
          const Spacer(),
        ])
      ),
      _tableWattFrom(),
      Container(
        color: ConstValue.colorForeUiBack1,
        child: Row(children: [
          const SizedBox(width:5),
          Text(AppLocalizations.of(context)!.fromMinute,
            style: const TextStyle(
              color: ConstValue.colorForeFrom,
              fontSize: 12
            )
          ),
          const Spacer(),
        ])
      ),
      _tableMinute(),
      Container(
        color: ConstValue.colorForeUiBack1,
        child: Row(children: [
          const SizedBox(width:5),
          Text(AppLocalizations.of(context)!.fromSecond,
            style: const TextStyle(
              color: ConstValue.colorForeFrom,
              fontSize: 12
            )
          ),
          const Spacer(),
        ])
      ),
      _tableSecond(),
      const SizedBox(height:10),
      Container(
        color: ConstValue.colorForeUiBack1,
        child: Row(children: [
          const SizedBox(width:5),
          Text(AppLocalizations.of(context)!.wattTo,
            style: const TextStyle(
              color: ConstValue.colorForeTo,
              fontSize: 12
            )
          ),
          const Spacer(),
        ])
      ),
      _tableWattTo(),
      const SizedBox(height:10),
      Container(
        color: Colors.white,
        child: Padding(
        padding: const EdgeInsets.only(top: 5, left: 0, right: 0, bottom: 5),
          child: Column(children:[
            Row(children: [
              const Spacer(),
              Text('${AppLocalizations.of(context)!.specified} ${_wattFrom}W ${_minute} ${AppLocalizations.of(context)!.minute} ${_second} ${AppLocalizations.of(context)!.second}',
                style: const TextStyle(
                  color: ConstValue.colorForeFrom,
                  fontSize: 15
                )
              ),
              const Spacer(),
            ]),
            Row(children: [
              const Spacer(),
              Text('${AppLocalizations.of(context)!.conversion} ${_wattTo}W ${answerMinute} ${AppLocalizations.of(context)!.minute} ${answerSecond} ${AppLocalizations.of(context)!.second}',
                style: const TextStyle(
                  color: ConstValue.colorForeTo,
                  fontSize:15
                )
              ),
              const Spacer(),
            ])
          ])
        )
      )
    ]);
  }
  //table
  Table _tableWattFrom() {
    if (_screenWidth >= 400) {
      return Table(
          children: <TableRow>[
            TableRow(children: <Widget>[
              _wattFromCell(300),
              _wattFromCell(400),
              _wattFromCell(500),
              _wattFromCell(600),
              _wattFromCell(700),
            ]),
            TableRow(children: <Widget>[
              _wattFromCell(800),
              _wattFromCell(900),
              _wattFromCell(1000),
              _wattFromCell(1100),
              _wattFromCell(1200),
            ]),
            TableRow(children: <Widget>[
              _wattFromCell(1300),
              _wattFromCell(1400),
              _wattFromCell(1500),
              _wattFromCell(1600),
              _wattFromCell(1700),
            ]),
          ]
      );
    } else {
      return Table(
          children: <TableRow>[
            TableRow(children: <Widget>[
              _wattFromCell(300),
              _wattFromCell(400),
              _wattFromCell(500),
              _wattFromCell(600),
            ]),
            TableRow(children: <Widget>[
              _wattFromCell(700),
              _wattFromCell(800),
              _wattFromCell(900),
              _wattFromCell(1000),
            ]),
            TableRow(children: <Widget>[
              _wattFromCell(1100),
              _wattFromCell(1200),
              _wattFromCell(1300),
              _wattFromCell(1400),
            ]),
            TableRow(children: <Widget>[
              _wattFromCell(1500),
              _wattFromCell(1600),
              _wattFromCell(1700),
              _wattFromCell(0),
            ]),
          ]
      );
    }
  }
  //table
  Table _tableMinute() {
    if (_screenWidth >= 400) {
      return Table(
        children: <TableRow>[
          TableRow(children: <Widget>[
            _minuteCell(1),
            _minuteCell(2),
            _minuteCell(3),
            _minuteCell(4),
            _minuteCell(5),
            _minuteCell(6),
          ]),
          TableRow(children: <Widget>[
            _minuteCell(7),
            _minuteCell(8),
            _minuteCell(9),
            _minuteCell(10),
            _minuteCell(11),
            _minuteCell(12),
          ]),
          TableRow(children: <Widget>[
            _minuteCell(13),
            _minuteCell(14),
            _minuteCell(15),
            _minuteCell(16),
            _minuteCell(17),
            _minuteCell(18),
          ]),
          TableRow(children: <Widget>[
            _minuteCell(19),
            _minuteCell(20),
            _minuteCell(21),
            _minuteCell(22),
            _minuteCell(23),
            _minuteCell(24),
          ]),
        ]
      );
    } else {
      return Table(
        children: <TableRow>[
          TableRow(children: <Widget>[
            _minuteCell(1),
            _minuteCell(2),
            _minuteCell(3),
            _minuteCell(4),
            _minuteCell(5),
          ]),
          TableRow(children: <Widget>[
            _minuteCell(6),
            _minuteCell(7),
            _minuteCell(8),
            _minuteCell(9),
            _minuteCell(10),
          ]),
          TableRow(children: <Widget>[
            _minuteCell(11),
            _minuteCell(12),
            _minuteCell(13),
            _minuteCell(14),
            _minuteCell(15),
          ]),
          TableRow(children: <Widget>[
            _minuteCell(16),
            _minuteCell(17),
            _minuteCell(18),
            _minuteCell(19),
            _minuteCell(20),
          ]),
          TableRow(children: <Widget>[
            _minuteCell(21),
            _minuteCell(22),
            _minuteCell(23),
            _minuteCell(24),
            _minuteCell(0),
          ]),
        ]
      );
    }
  }
  //table
  Table _tableSecond() {
    if (_screenWidth >= 400) {
      return Table(
          children: <TableRow>[
            TableRow(children: <Widget>[
              _secondCell(0),
              _secondCell(10),
              _secondCell(20),
              _secondCell(30),
              _secondCell(40),
              _secondCell(50),
            ]),
          ]
      );
    } else {
      return Table(
        children: <TableRow>[
          TableRow(children: <Widget>[
            _secondCell(0),
            _secondCell(10),
            _secondCell(20),
          ]),
          TableRow(children: <Widget>[
            _secondCell(30),
            _secondCell(40),
            _secondCell(50),
          ]),
        ]
      );
    }
  }
  //table
  Table _tableWattTo() {
    if (_screenWidth >= 400) {
      return Table(
          children: <TableRow>[
            TableRow(children: <Widget>[
              _wattToCell(300),
              _wattToCell(400),
              _wattToCell(500),
              _wattToCell(600),
              _wattToCell(700),
            ]),
            TableRow(children: <Widget>[
              _wattToCell(800),
              _wattToCell(900),
              _wattToCell(1000),
              _wattToCell(1100),
              _wattToCell(1200),
            ]),
            TableRow(children: <Widget>[
              _wattToCell(1300),
              _wattToCell(1400),
              _wattToCell(1500),
              _wattToCell(1600),
              _wattToCell(1700),
            ]),
          ]
      );
    } else {
      return Table(
          children: <TableRow>[
            TableRow(children: <Widget>[
              _wattToCell(300),
              _wattToCell(400),
              _wattToCell(500),
              _wattToCell(600),
            ]),
            TableRow(children: <Widget>[
              _wattToCell(700),
              _wattToCell(800),
              _wattToCell(900),
              _wattToCell(1000),
            ]),
            TableRow(children: <Widget>[
              _wattToCell(1100),
              _wattToCell(1200),
              _wattToCell(1300),
              _wattToCell(1400),
            ]),
            TableRow(children: <Widget>[
              _wattToCell(1500),
              _wattToCell(1600),
              _wattToCell(1700),
              _wattToCell(0),
            ]),
          ]
      );
    }
  }
  //cell
  TableCell _wattFromCell(int number) {
    if (number == 0) {
      return TableCell(
        child:Container(
          height: 28,
          color: ConstValue.colorForeUiBack2,
        )
      );
    } else {
      return TableCell(
        child: Container(
          height: 28.0,
          color: (_wattFrom == number) ? ConstValue.colorForeFrom : ConstValue.colorForeUiBack2,
          child: Transform.translate(
            offset: const Offset(-5, -5),
            child: RadioListTile(
              visualDensity: const VisualDensity(
                horizontal: VisualDensity.minimumDensity,
                vertical: VisualDensity.minimumDensity
              ),
              contentPadding: EdgeInsets.zero,
              title: Transform.translate(
                offset: const Offset(-12, 0),
                child: Text(number.toString(),
                  style: TextStyle(
                    color: (_wattFrom == number) ? Colors.white : Colors.black,
                    fontSize: 12
                  )
                )
              ),
              value: number,
              groupValue: _wattFrom,
              onChanged: (int? value) {
                setState(() {
                  _wattFrom = value ?? 0;
                  Preferences.setWattFrom(_wattFrom);
                });
              },
              activeColor: ConstValue.colorForeUiActiveColor,
            )
          )
        )
      );
    }
  }
  //cell
  TableCell _minuteCell(int number) {
    if (number == 0) {
      return TableCell(
        child:Container(
          height: 28,
          color: ConstValue.colorForeUiBack2,
        )
      );
    } else {
      return TableCell(
        child: Container(
          height: 28.0,
          color: (_minute == number) ? ConstValue.colorForeFrom : ConstValue.colorForeUiBack2,
          child: Transform.translate(
            offset: const Offset(-5, -5),
            child: RadioListTile(
              visualDensity: const VisualDensity(
                horizontal: VisualDensity.minimumDensity,
                vertical: VisualDensity.minimumDensity
              ),
              materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
              contentPadding: EdgeInsets.zero,
              title: Transform.translate(
                offset: const Offset(-12, 0),
                child: Text(number.toString(),
                  style: TextStyle(
                    color: (_minute == number) ? Colors.white : Colors.black,
                    fontSize: 12
                  )
                )
              ),
              value: number,
              groupValue: _minute,
              onChanged: (int? value) {
                setState(() {
                  _minute = value ?? 0;
                  Preferences.setMinute(_minute);
                });
              },
              activeColor: ConstValue.colorForeUiActiveColor,
            )
          )
        )
      );
    }
  }
  //cell
  TableCell _secondCell(int number) {
    if (number == 0) {
      return TableCell(
        child:Container(
          height: 28,
          color: ConstValue.colorForeUiBack2,
        )
      );
    } else {
      return TableCell(
        child: Container(
          height: 28.0,
          color: (_second == number) ? ConstValue.colorForeFrom : ConstValue.colorForeUiBack2,
          child: Transform.translate(
            offset: const Offset(-5, -5),
            child: RadioListTile(
              visualDensity: const VisualDensity(
                horizontal: VisualDensity.minimumDensity,
                vertical: VisualDensity.minimumDensity
              ),
              materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
              contentPadding: EdgeInsets.zero,
              title: Transform.translate(
                offset: const Offset(-12, 0),
                child: Text(number.toString(),
                  style: TextStyle(
                    color: (_second == number) ? Colors.white : Colors.black,
                    fontSize: 12
                  )
                )
              ),
              value: number,
              groupValue: _second,
              onChanged: (int? value) {
                setState(() {
                  _second = value ?? 0;
                  Preferences.setSecond(_second);
                });
              },
              activeColor: ConstValue.colorForeUiActiveColor,
            )
          )
        )
      );
    }
  }
  //cell
  TableCell _wattToCell(int number) {
    if (number == 0) {
      return TableCell(
        child:Container(
          height: 28,
          color: ConstValue.colorForeUiBack2,
        )
      );
    } else {
      return TableCell(
        child: Container(
          height: 28.0,
          color: (_wattTo == number) ? ConstValue.colorForeTo : ConstValue.colorForeUiBack2,
          child: Transform.translate(
            offset: const Offset(-5, -5),
            child: RadioListTile(
              visualDensity: const VisualDensity(
                horizontal: VisualDensity.minimumDensity,
                vertical: VisualDensity.minimumDensity
              ),
              contentPadding: EdgeInsets.zero,
              title: Transform.translate(
                offset: const Offset(-12, 0),
                child: Text(number.toString(),
                  style: TextStyle(
                    color: (_wattTo == number) ? Colors.white : Colors.black,
                    fontSize: 12
                  )
                )
              ),
              value: number,
              groupValue: _wattTo,
              onChanged: (int? value) {
                setState(() {
                  _wattTo = value ?? 0;
                  Preferences.setWattTo(_wattTo);
                });
              },
              activeColor: ConstValue.colorForeUiActiveColor,
            )
          )
        )
      );
    }
  }

}

lib/page_state.dart

///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2023-10-05
///
library;

//現在のページを記録。initStateでタイミングが合わない時にbuild内で一度だけ実行させるために使用。
class PageState {

  static String _currentPage = '';

  static void setCurrentPage(String str) {
    _currentPage = str;
  }

  static String getCurrentPage() {
    return _currentPage;
  }

}

lib/preferences.dart

///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2023-10-26
///
library;

import 'package:shared_preferences/shared_preferences.dart';

import 'package:wattconversion/const_value.dart';

//デバイスに情報を保存
class Preferences {

  static bool ready = false;
  //この値は常に最新にしておく
  static String _languageCode = '';
  static bool _showBackImage = true;
  static double _soundVolume = 0.3;
  static int _wattFrom = 600;
  static int _wattTo = 500;
  static int _minute = 5;
  static int _second = 0;

  static String get languageCode {
    return _languageCode;
  }
  static bool get showBackImage {
    return _showBackImage;
  }
  static double get soundVolume {
    return _soundVolume;
  }
  static int get wattFrom {
    return _wattFrom;
  }
  static int get wattTo {
    return _wattTo;
  }
  static int get minute {
    return _minute;
  }
  static int get second {
    return _second;
  }

  static Future<void> initial() async {
    _languageCode = await getLanguageCode();
    _showBackImage = await getShowBackImage();
    _soundVolume = await getSoundVolume();
    _wattFrom = await getWattFrom();
    _wattTo = await getWattTo();
    _minute = await getMinute();
    _second = await getSecond();
    ready = true;
  }

  //----------------------------

  //言語コード
  static Future<void> setLanguageCode(String str) async {
    _languageCode = str;
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setString(ConstValue.prefLanguageCode, str);
  }
  static Future<String> getLanguageCode() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final String str = prefs.getString(ConstValue.prefLanguageCode) ?? 'en';
    return str;
  }

  //----------------------------

  //背景画像表示
  static Future<void> setShowBackImage(bool flag) async {
    _showBackImage = flag;
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setBool(ConstValue.prefShowBackImage, flag);
  }
  static Future<bool> getShowBackImage() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final bool flag = prefs.getBool(ConstValue.prefShowBackImage) ?? true;
    return flag;
  }

  //----------------------------

  //効果音音量
  static Future<void> setSoundVolume(double num) async {
    _soundVolume = num;
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setDouble(ConstValue.prefSoundVolume, num);
  }
  static Future<double> getSoundVolume() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final double num = prefs.getDouble(ConstValue.prefSoundVolume) ?? 0.3;
    return num;
  }

  //----------------------------

  //watt from
  static Future<void> setWattFrom(int num) async {
    _wattFrom = num;
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setInt(ConstValue.prefWattFrom, num);
  }
  static Future<int> getWattFrom() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final int num = prefs.getInt(ConstValue.prefWattFrom) ?? 600;
    return num;
  }

  //----------------------------

  //watt to
  static Future<void> setWattTo(int num) async {
    _wattTo = num;
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setInt(ConstValue.prefWattTo, num);
  }
  static Future<int> getWattTo() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final int num = prefs.getInt(ConstValue.prefWattTo) ?? 500;
    return num;
  }
  //----------------------------

  //minute
  static Future<void> setMinute(int num) async {
    _minute = num;
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setInt(ConstValue.prefMinute, num);
  }
  static Future<int> getMinute() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final int num = prefs.getInt(ConstValue.prefMinute) ?? 5;
    return num;
  }

  //----------------------------

  //second
  static Future<void> setSecond(int num) async {
    _second = num;
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setInt(ConstValue.prefSecond, num);
  }
  static Future<int> getSecond() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final int num = prefs.getInt(ConstValue.prefSecond) ?? 0;
    return num;
  }

//----------------------------

}

lib/setting.dart

///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2023-10-15
///
library;

import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

import 'package:wattconversion/const_value.dart';
import 'package:wattconversion/preferences.dart';
import 'package:wattconversion/language_state.dart';
import 'package:wattconversion/version_state.dart';
import 'package:wattconversion/ad_mob.dart';
import 'package:wattconversion/page_state.dart';

class SettingPage extends StatefulWidget {
  const SettingPage({super.key});

  @override
  State<SettingPage> createState() => _SettingPageState();
}

class _SettingPageState extends State<SettingPage> {
  final AdMob _adMob = AdMob(); //広告
  //これら変数はUIへの表示や入力の為に一時的に使用される。
  String _languageKey = ''; //言語コード 'en'
  String _languageValue = '';
  bool _showBackImage = true;
  double _soundVolume = 0.0;

  //ページ起動時に一度だけ実行される
  @override
  void initState() {
    super.initState();
    _adMob.load();
  }
  //ページ終了時に一度だけ実行される
  @override
  void dispose() {
    PageState.setCurrentPage('');
    _adMob.dispose();
    super.dispose();
  }
  //ページ描画
  @override
  Widget build(BuildContext context) {
    //このページが開いたときに一度だけ実行される処理を記述。initStateではタイミングが合わない為。
    if (PageState.getCurrentPage() != 'setting') {
      PageState.setCurrentPage('setting');
      (() async {
        _languageKey = await LanguageState.getLanguageCode();
        _languageValue = ConstValue.languageCode[_languageKey] ?? '';
        await Preferences.initial();
        _showBackImage = Preferences.showBackImage;
        _soundVolume = Preferences.soundVolume;
        setState((){});
      })();
    }
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        elevation: 0,
        //設定キャンセルボタン
        leading: IconButton(
          icon: const Icon(Icons.close),
          onPressed: () {
            Navigator.of(context).pop(false); //falseを返す
          },
        ),
        title: Text(AppLocalizations.of(context)!.setting),
        foregroundColor: const Color.fromRGBO(255,255,255,1),
        backgroundColor: ConstValue.colorSettingHeader,
        actions: [
          //設定OKボタン
          IconButton(
            icon: const Icon(Icons.check),
            onPressed: () async {
              await LanguageState.setLanguageCode(_languageKey);
              await Preferences.setShowBackImage(_showBackImage);
              await Preferences.setSoundVolume(_soundVolume);
              if (!mounted) {
                return;
              }
              Navigator.of(context).pop(true);  //trueを返す
            },
          ),
        ],
      ),
      body: Column(children:[
        Expanded(
          child: GestureDetector(
            onTap: () => FocusScope.of(context).unfocus(),  //背景タップでキーボードを仕舞う
            child: SingleChildScrollView(
              child: Padding(
                padding: const EdgeInsets.all(20),
                child: Column(children: [
                  Padding(
                    padding: const EdgeInsets.only(top: 16, left: 16, right: 16, bottom: 16),
                    child: Row(children:<Widget>[
                      Expanded(
                        child: Text(AppLocalizations.of(context)!.showBackImage,style: const TextStyle(fontSize: 16)),
                      ),
                      Switch(
                        value: _showBackImage,
                        onChanged: (bool value) {
                          setState(() {
                            _showBackImage = value;
                          });
                        },
                        activeColor: ConstValue.colorSettingUiActiveColor,
                        inactiveThumbColor: ConstValue.colorUiInactiveColor,
                      ),
                    ]),
                  ),
                  _border(),
                  Padding(
                    padding: const EdgeInsets.only(top: 18, left: 16, right: 16, bottom: 0),
                    child: Row(children: [
                      Text(AppLocalizations.of(context)!.soundVolume,style: const TextStyle(fontSize: 16)),
                      const Spacer(),
                    ])
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 0, left: 16, right: 16, bottom: 6),
                    child: Row(children: <Widget>[
                      Text(_soundVolume.toString()),
                      Expanded(
                        child: Slider(
                          value: _soundVolume,
                          min: 0.0,
                          max: 1.0,
                          divisions: 10,
                          onChanged: (double value) {
                            setState(() {
                              _soundVolume = value;
                            });
                          },
                          activeColor: ConstValue.colorSettingUiActiveColor,
                          inactiveColor: ConstValue.colorUiInactiveColor,
                        )
                      )
                    ])
                  ),
                  _border(),
                  Padding(
                    padding: const EdgeInsets.only(top: 18, left: 0, right: 0, bottom: 0),
                    child: Row(children:[
                      const SizedBox(width:16),
                      Text(AppLocalizations.of(context)!.language,
                        style: const TextStyle(
                          fontSize: 16,
                        )
                      ),
                      const Spacer(),
                    ])
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 12, left: 0, right: 0, bottom: 18),
                    child: Table(
                      children: <TableRow>[
                        TableRow(children: <Widget>[
                          _languageTableCell(0),
                          _languageTableCell(1),
                        ]),
                        TableRow(children: <Widget>[
                          _languageTableCell(2),
                          _languageTableCell(3),
                        ]),
                        TableRow(children: <Widget>[
                          _languageTableCell(4),
                          _languageTableCell(5),
                        ]),
                        TableRow(children: <Widget>[
                          _languageTableCell(6),
                          _languageTableCell(7),
                        ]),
                        TableRow(children: <Widget>[
                          _languageTableCell(8),
                          _languageTableCell(9),
                        ]),
                        TableRow(children: <Widget>[
                          _languageTableCell(10),
                          _languageTableCell(11),
                        ]),
                        TableRow(children: <Widget>[
                          _languageTableCell(12),
                          _languageTableCell(13),
                        ]),
                        TableRow(children: <Widget>[
                          _languageTableCell(14),
                          _languageTableCell(15),
                        ]),
                        TableRow(children: <Widget>[
                          _languageTableCell(16),
                          _languageTableCell(17),
                        ]),
                        TableRow(children: <Widget>[
                          _languageTableCell(18),
                          _languageTableCell(19),
                        ]),
                        TableRow(children: <Widget>[
                          _languageTableCell(20),
                          _languageTableCell(21),
                        ]),
                        TableRow(children: <Widget>[
                          _languageTableCell(22),
                          _languageTableCell(23),
                        ]),
                      ]
                    ),
                  ),
                  _border(),
                  Padding(
                    padding: const EdgeInsets.only(top: 24, left: 0, right: 0, bottom: 24),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children:[
                        Text(AppLocalizations.of(context)!.usage1),
                        const SizedBox(height:15),
                        Text(AppLocalizations.of(context)!.usage2),
                        const SizedBox(height:15),
                        Text(AppLocalizations.of(context)!.usage3),
                        const SizedBox(height:15),
                        Text(AppLocalizations.of(context)!.usage4),
                      ]
                    ),
                  ),
                  _border(),
                  Padding(
                    padding: const EdgeInsets.only(top: 24, left: 0, right: 0, bottom: 36),
                    child: SizedBox(
                      child: Text('version  ${VersionState.versionLoad()}',
                        style: const TextStyle(
                          fontSize: 10,
                        ),
                      ),
                    ),
                  ),
                ]),
              ),
            ),
          ),
        ),
        Padding(
          padding: const EdgeInsets.only(top: 10, left: 0, right: 0, bottom: 0),
          child: SizedBox(
            width: double.infinity,
            child: _adMob.getAdBannerWidget(),
          ),
        ),
      ]),
    );
  }
  //UIの仕切り用ボーダーライン
  Widget _border() {
    return Container(
      decoration: BoxDecoration(
        border: Border(
          top: BorderSide(
            color: Colors.grey.shade300,
            width: 1,
          ),
        ),
      ),
    );
  }
  //言語一覧表示
  TableCell _languageTableCell(int index) {
    return TableCell(
      child: RadioListTile(
        visualDensity: const VisualDensity(horizontal: VisualDensity.minimumDensity,vertical: VisualDensity.minimumDensity),
        contentPadding: EdgeInsets.zero,
        title: Text(ConstValue.languageCode.values.elementAt(index)),
        value: ConstValue.languageCode.values.elementAt(index),
        groupValue: _languageValue,
        onChanged: (String? value) {
          setState(() {
            _languageValue = value ?? '';
            _languageKey = ConstValue.languageCode.keys.elementAt(index);
          });
        },
        activeColor: ConstValue.colorSettingUiActiveColor,
      ),
    );
  }

}

lib/version_state.dart

///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2023-01-27
///
library;

class VersionState {

  static String _version = '';

  //バージョンを記録
  static void versionSave(String str) {
    _version = str;
  }
  //バージョンを返す
  static String versionLoad() {
    return _version;
  }

}

lib/l10n/app_bg.arb

{
	"@@locale":"bg",
	"@locale": {
		"description": "ブルガリア"
	},
	"title": "Преобразуване на мощността на микровълновата фурна",
	"setting": "Настройка",
	"wattFrom": "Определена мощност",
	"wattTo": "Целева мощност",
	"fromMinute": "Определена минута",
	"fromSecond": "посочено второ",
	"specified": "Уточнено",
	"conversion": "Преобразуване",
	"minute": "минута",
	"second": "второ",
	"showBackImage": "Показване на фоново изображение",
	"soundVolume": "Сила на звука на звуковия ефект",
	"language": "език",
	"usage1": "Преобразуване на мощността на микровълновата фурна",
	"usage2": "Преобразува времето за готвене за микровълновата фурна въз основа на мощността на вашата микровълнова фурна.",
	"usage3": "Въпреки че очакваното време за готвене за микровълнови фурни може да бъде предоставено на опаковката на храната, може да има случаи, когато мощността на вашата микровълнова фурна не съвпада.В такива случаи тя изчислява и показва подходящото време за готвене чрез преобразуване на мощността.",
	"usage4": "Забележка: Числата не са непременно точни.",

	"dummy": "dummy"
}

lib/l10n/app_cs.arb

{
	"@@locale":"cs",
	"@locale": {
		"description": "チェコ"
	},
	"title": "Přeměna výkonu mikrovlnné trouby",
	"setting": "Nastavení",
	"wattFrom": "Uvedený příkon",
	"wattTo": "Cílový výkon",
	"fromMinute": "Zadaná minuta",
	"fromSecond": "specifikovaná druhá",
	"specified": "Upřesněno",
	"conversion": "Konverze",
	"minute": "minuta",
	"second": "druhý",
	"showBackImage": "Zobrazit obrázek na pozadí",
	"soundVolume": "Hlasitost zvukového efektu",
	"language": "Jazyk",
	"usage1": "Přeměna výkonu mikrovlnné trouby",
	"usage2": "Převádí doby vaření pro mikrovlnnou troubu na základě příkonu vaší mikrovlnné trouby.",
	"usage3": "Ačkoli mohou být na obalech potravin uvedeny odhady doby vaření pro mikrovlnné trouby, mohou nastat případy, kdy příkon vaší mikrovlnné trouby neodpovídá.V takových případech vypočítá a zobrazí vhodnou dobu vaření převodem výkonu ve wattech.",
	"usage4": "Poznámka: Čísla nemusí být nutně přesná.",

	"dummy": "dummy"
}

lib/l10n/app_da.arb

{
	"@@locale":"da",
	"@locale": {
		"description": "デンマーク"
	},
	"title": "Mikrobølgeovns effektkonvertering",
	"setting": "Indstilling",
	"wattFrom": "Specificeret watt",
	"wattTo": "Mål watt",
	"fromMinute": "Angivet minut",
	"fromSecond": "specificeret anden",
	"specified": "Specificeret",
	"conversion": "Konvertering",
	"minute": "minut",
	"second": "anden",
	"showBackImage": "Vis baggrundsbillede",
	"soundVolume": "Lydeffekt lydstyrke",
	"language": "Sprog",
	"usage1": "Mikrobølgeovns effektkonvertering",
	"usage2": "Konverterer tilberedningstiden for mikrobølgeovnen baseret på din mikrobølgeovns watt.",
	"usage3": "Selvom anslåede tilberedningstid for mikrobølgeovne kan være angivet på fødevareemballagen, kan der være tilfælde, hvor din mikrobølgeovns watttal ikke stemmer overens. I sådanne tilfælde beregner og viser den den passende tilberedningstid ved at konvertere watttallet.",
	"usage4": "Bemærk: Tallene er ikke nødvendigvis nøjagtige.",

	"dummy": "dummy"
}

lib/l10n/app_de.arb

{
	"@@locale":"de",
	"@locale": {
		"description": "ドイツ"
	},
	"title": "Umrechnung der Mikrowellen-Wattleistung",
	"setting": "Einstellung",
	"wattFrom": "Angegebene Wattzahl",
	"wattTo": "Zielwattzahl",
	"fromMinute": "Angegebene Minute",
	"fromSecond": "Sekunde angegeben",
	"specified": "Angegeben",
	"conversion": "Konvertierung",
	"minute": "Minute",
	"second": "zweite",
	"showBackImage": "Hintergrundbild anzeigen",
	"soundVolume": "Lautstärke des Soundeffekts",
	"language": "Sprache",
	"usage1": "Umrechnung der Mikrowellen-Wattleistung",
	"usage2": "Rechnet die Garzeiten für die Mikrowelle basierend auf der Wattzahl Ihres Mikrowellenherds um.",
	"usage3": "Obwohl auf Lebensmittelverpackungen möglicherweise Schätzungen zur Garzeit für Mikrowellenherde angegeben sind, kann es vorkommen, dass die Wattzahl Ihres Mikrowellenherds nicht übereinstimmt. In solchen Fällen berechnet das Gerät die entsprechende Garzeit durch Umrechnung der Wattzahl und zeigt sie an.",
	"usage4": "Hinweis: Die Zahlen sind nicht unbedingt korrekt.",

	"dummy": "dummy"
}

lib/l10n/app_el.arb

{
	"@@locale":"el",
	"@locale": {
		"description": "ギリシャ"
	},
	"title": "Μετατροπή ισχύος φούρνου μικροκυμάτων",
	"setting": "Σύνθεση",
	"wattFrom": "Καθορισμένη ισχύς",
	"wattTo": "Η ισχύς στόχος",
	"fromMinute": "Καθορισμένο λεπτό",
	"fromSecond": "καθορισμένο δεύτερο",
	"specified": "Καθορίζεται",
	"conversion": "Μετατροπή",
	"minute": "λεπτό",
	"second": "δεύτερος",
	"showBackImage": "Εμφάνιση εικόνας φόντου",
	"soundVolume": "Ένταση ήχου εφέ",
	"language": "Γλώσσα",
	"usage1": "Μετατροπή ισχύος φούρνου μικροκυμάτων",
	"usage2": "Μετατρέπει τους χρόνους μαγειρέματος για το φούρνο μικροκυμάτων με βάση την ισχύ του φούρνου μικροκυμάτων σας.",
	"usage3": "Παρόλο που μπορεί να παρέχονται εκτιμήσεις χρόνου μαγειρέματος για φούρνους μικροκυμάτων στη συσκευασία των τροφίμων, μπορεί να υπάρχουν περιπτώσεις όπου η ισχύς του φούρνου μικροκυμάτων σας δεν ταιριάζει. Σε τέτοιες περιπτώσεις, υπολογίζει και εμφανίζει τον κατάλληλο χρόνο μαγειρέματος μετατρέποντας την ισχύ.",
	"usage4": "Σημείωση: Οι αριθμοί δεν είναι απαραίτητα ακριβείς.",

	"dummy": "dummy"
}

lib/l10n/app_en.arb

{
	"@@locale":"en",
	"@locale": {
		"description": "英語"
	},
	"title": "Microwave Oven Wattage Conversion",
	"setting": "Setting",
    "wattFrom": "Specified wattage",
    "wattTo": "Target wattage",
    "fromMinute": "Specified minute",
    "fromSecond": "specified second",
	"specified": "Specified",
	"conversion": "Conversion",
	"minute": "minute",
	"second": "second",
    "showBackImage": "Show Background image",
	"soundVolume": "Sound Effect Volume",
	"language": "Language",
    "usage1": "Microwave Oven Wattage Conversion",
    "usage2": "Converts cooking times for the microwave based on the wattage of your microwave oven.",
    "usage3": "Although cooking time estimates for microwave ovens may be provided on food packaging, there could be instances where the wattage of your microwave oven does not match. In such cases, it calculates and displays the appropriate cooking time by converting the wattage.",
	"usage4": "Note: Numbers are not necessarily accurate.",

	"dummy": "dummy"
}

lib/l10n/app_es.arb

{
	"@@locale":"es",
	"@locale": {
		"description": "スペイン"
	},
	"title": "Conversión de potencia del horno microondas",
	"setting": "Configuración",
	"wattFrom": "Potencia especificada",
	"wattTo": "Potencia objetivo",
	"fromMinute": "Minuto especificado",
	"fromSecond": "segundo especificado",
	"specified": "Especificado",
	"conversion": "Conversión",
	"minute": "minuto",
	"second": "segundo",
	"showBackImage": "Mostrar imagen de fondo",
	"soundVolume": "Volumen del efecto de sonido",
	"language": "Idioma",
	"usage1": "Conversión de potencia del horno microondas",
	"usage2": "Convierte los tiempos de cocción del microondas según la potencia de su horno microondas.",
	"usage3": "Aunque se pueden proporcionar estimaciones del tiempo de cocción para hornos microondas en el paquete de alimentos, puede haber casos en los que la potencia de su horno microondas no coincida. En tales casos, calcula y muestra el tiempo de cocción apropiado convirtiendo la potencia.",
	"usage4": "Nota: Las cifras no son necesariamente exactas.",

	"dummy": "dummy"
}

lib/l10n/app_et.arb

{
	"@@locale":"et",
	"@locale": {
		"description": "エストニア"
	},
	"title": "Mikrolaineahju võimsuse teisendamine",
	"setting": "Seadistamine",
	"wattFrom": "Määratud võimsus",
	"wattTo": "Sihtvõimsus",
	"fromMinute": "Määratud minut",
	"fromSecond": "täpsustatud teiseks",
	"specified": "Määratud",
	"conversion": "Teisendamine",
	"minute": "minut",
	"second": "teiseks",
	"showBackImage": "Näita taustapilti",
	"soundVolume": "Heliefekti helitugevus",
	"language": "Keel",
	"usage1": "Mikrolaineahju võimsuse teisendamine",
	"usage2": "Teisendab mikrolaineahju küpsetusajad teie mikrolaineahju võimsuse põhjal.",
	"usage3": "Kuigi mikrolaineahjude küpsetusaja hinnangud võivad olla toidupakendil, võib juhtuda, et teie mikrolaineahju võimsus ei ühti. Sellistel juhtudel arvutab ja kuvab see sobiva küpsetusaja võimsuse teisendamise teel.",
	"usage4": "Märkus. Numbrid ei pruugi olla täpsed.",

	"dummy": "dummy"
}

lib/l10n/app_fi.arb

{
	"@@locale":"fi",
	"@locale": {
		"description": "フィンランド"
	},
	"title": "Mikroaaltouunin tehon muunnos",
	"setting": "Asetus",
	"wattFrom": "Ilmoitettu wattiteho",
	"wattTo": "Tavoite wattimäärä",
	"fromMinute": "Määrätty minuutti",
	"fromSecond": "määritelty toiseksi",
	"specified": "Määritetty",
	"conversion": "Muuntaminen",
	"minute": "minuutti",
	"second": "toinen",
	"showBackImage": "Näytä taustakuva",
	"soundVolume": "Äänitehosteen äänenvoimakkuus",
	"language": "Kieli",
	"usage1": "Mikroaaltouunin tehon muunnos",
	"usage2": "Muuntaa mikroaaltouunin kypsennysajat mikroaaltouunisi tehon perusteella.",
	"usage3": "Vaikka mikroaaltouunien kypsennysaika-arviot voivat olla ruokapakkauksissa, mikroaaltouunisi teho ei välttämättä täsmää. Tällöin se laskee ja näyttää sopivan kypsennysajan muuntamalla tehon.",
	"usage4": "Huomaa: Numerot eivät välttämättä ole tarkkoja.",

	"dummy": "dummy"
}

lib/l10n/app_fr.arb

{
	"@@locale":"fr",
	"@locale": {
		"description": "フランス"
	},
	"title": "Conversion de puissance du four à micro-ondes",
	"setting": "Paramètre",
	"wattFrom": "Puissance spécifiée",
	"wattTo": "Puissance cible",
	"fromMinute": "Minute spécifiée",
	"fromSecond": "seconde spécifiée",
	"specified": "Spécifié",
	"conversion": "Conversion",
	"minute": "minute",
	"second": "deuxième",
	"showBackImage": "Afficher l'image d'arrière-plan",
	"soundVolume": "Volume des effets sonores",
	"language": "Langue",
	"usage1": "Conversion de puissance du four à micro-ondes",
	"usage2": "Convertit les temps de cuisson pour le micro-ondes en fonction de la puissance de votre four à micro-ondes.",
	"usage3": "Bien que les estimations du temps de cuisson des fours à micro-ondes puissent être fournies sur les emballages alimentaires, il peut arriver que la puissance de votre four à micro-ondes ne corresponde pas. Dans de tels cas, il calcule et affiche le temps de cuisson approprié en convertissant la puissance.",
	"usage4": "Remarque: Les chiffres ne sont pas nécessairement exacts.",

	"dummy": "dummy"
}

lib/l10n/app_hu.arb

{
	"@@locale":"hu",
	"@locale": {
		"description": "ハンガリー"
	},
	"title": "Mikrohullámú sütő teljesítményének átalakítása",
	"setting": "Beállítás",
	"wattFrom": "Megadott teljesítmény",
	"wattTo": "Cél watt",
	"fromMinute": "Meghatározott perc",
	"fromSecond": "meghatározott második",
	"specified": "Meghatározott",
	"conversion": "Átalakítás",
	"minute": "perc",
	"second": "második",
	"showBackImage": "Háttérkép megjelenítése",
	"soundVolume": "Hangeffektus hangereje",
	"language": "Nyelv",
	"usage1": "Mikrohullámú sütő teljesítményének átalakítása",
	"usage2": "Átalakítja a mikrohullámú sütő főzési idejét a mikrohullámú sütő teljesítménye alapján.",
	"usage3": "Bár a mikrohullámú sütők főzési idejére vonatkozó becslések szerepelhetnek az élelmiszerek csomagolásán, előfordulhatnak olyan esetek, amikor az Ön mikrohullámú sütőjének teljesítménye nem egyezik. Ilyen esetekben a teljesítmény átszámításával kiszámítja és megjeleníti a megfelelő főzési időt.",
	"usage4": "Megjegyzés: A számok nem feltétlenül pontosak.",

	"dummy": "dummy"
}

lib/l10n/app_it.arb

{
	"@@locale":"it",
	"@locale": {
		"description": "イタリア"
	},
	"title": "Conversione della potenza del forno a microonde",
	"setting": "Collocamento",
	"wattFrom": "Potenza specificata",
	"wattTo": "Potenza target",
	"fromMinute": "Minuto specificato",
	"fromSecond": "secondo specificato",
	"specified": "Specificato",
	"conversion": "Conversione",
	"minute": "minuto",
	"second": "secondo",
	"showBackImage": "Mostra immagine di sfondo",
	"soundVolume": "Volume dell'effetto sonoro",
	"language": "Lingua",
	"usage1": "Conversione della potenza del forno a microonde",
	"usage2": "Converte i tempi di cottura per il microonde in base alla potenza del tuo forno a microonde.",
	"usage3": "Sebbene le stime del tempo di cottura per i forni a microonde possano essere fornite sulla confezione degli alimenti, potrebbero esserci casi in cui la potenza del forno a microonde non corrisponde. In tali casi, calcola e visualizza il tempo di cottura appropriato convertendo la potenza.",
	"usage4": "Nota: i numeri non sono necessariamente accurati.",

	"dummy": "dummy"
}

lib/l10n/app_ja.arb

{
	"@@locale":"ja",
	"@locale": {
		"description": "日本"
	},
	"title": "電子レンジ ワット数換算",
	"setting": "設定",
	"wattFrom": "指定のワット数",
	"wattTo": "目標のワット数",
	"fromMinute": "指定の分",
	"fromSecond": "指定の秒",
	"specified": "指定",
	"conversion": "換算",
	"minute": "分",
	"second": "秒",
	"showBackImage": "背景画像表示",
	"soundVolume": "効果音の音量",
	"language": "言語",
	"usage1": "電子レンジ ワット数換算",
	"usage2": "手持ちの電子レンジのワット数に基づいて、電子レンジでの調理時間を換算します。",
	"usage3": "食品パッケージには電子レンジでの調理時間の目安が記載されていることがありますが、手持ちの電子レンジのワット数が一致しない場合があります。その際、ワット数を換算して適切な調理時間を表示します。",
	"usage4": "注意:数値は必ずしも正しいとは限りません。",

	"dummy": "dummy"
}

lib/l10n/app_lt.arb

{
	"@@locale":"lt",
	"@locale": {
		"description": "リトアニア"
	},
	"title": "Mikrobangų krosnelės galios konvertavimas",
	"setting": "Nustatymas",
	"wattFrom": "Nurodyta galia",
	"wattTo": "Tikslinė galia",
	"fromMinute": "Nurodyta minutė",
	"fromSecond": "nurodyta antra",
	"specified": "Nurodyta",
	"conversion": "Konversija",
	"minute": "minutė",
	"second": "antra",
	"showBackImage": "Rodyti foninį vaizdą",
	"soundVolume": "Garso efekto garsumas",
	"language": "Kalba",
	"usage1": "Mikrobangų krosnelės galios konvertavimas",
	"usage2": "Konvertuoja mikrobangų krosnelės gaminimo laiką pagal jūsų mikrobangų krosnelės galią.",
	"usage3": "Nors mikrobangų krosnelės gaminimo trukmė gali būti nurodyta ant maisto pakuočių, gali pasitaikyti atvejų, kai jūsų mikrobangų krosnelės galia nesutampa. Tokiais atvejais ji apskaičiuoja ir parodo tinkamą gaminimo laiką konvertuodama galingumą.",
	"usage4": "Pastaba: skaičiai nebūtinai tikslūs.",

	"dummy": "dummy"
}

lib/l10n/app_lv.arb

{
	"@@locale":"lv",
	"@locale": {
		"description": "ラトビア"
	},
	"title": "Mikroviļņu krāsns jaudas pārveidošana",
	"setting": "Iestatījums",
	"wattFrom": "Norādītā jauda",
	"wattTo": "Mērķa jauda",
	"fromMinute": "Norādītā minūte",
	"fromSecond": "norādīts otrais",
	"specified": "Norādīts",
	"conversion": "Pārvēršana",
	"minute": "minūte",
	"second": "otrais",
	"showBackImage": "Rādīt fona attēlu",
	"soundVolume": "Skaņas efekta skaļums",
	"language": "Valoda",
	"usage1": "Mikroviļņu krāsns jaudas pārveidošana",
	"usage2": "Pārvērš gatavošanas laikus mikroviļņu krāsnī, pamatojoties uz jūsu mikroviļņu krāsns jaudu.",
	"usage3": "Lai gan uz pārtikas iepakojuma var būt norādīts mikroviļņu krāsns gatavošanas laiks, var būt gadījumi, kad jūsu mikroviļņu krāsns jauda nesakrīt. Šādos gadījumos tā aprēķina un parāda atbilstošo gatavošanas laiku, pārvēršot jaudu.",
	"usage4": "Piezīme: skaitļi ne vienmēr ir precīzi.",

	"dummy": "dummy"
}

lib/l10n/app_nl.arb

{
	"@@locale":"nl",
	"@locale": {
		"description": "オランダ"
	},
	"title": "Wattageconversie van magnetronovens",
	"setting": "Instelling",
	"wattFrom": "Gespecificeerd wattage",
	"wattTo": "Doel wattage",
	"fromMinute": "Opgegeven minuut",
	"fromSecond": "opgegeven tweede",
	"specified": "Gespecificeerd",
	"conversion": "Conversie",
	"minute": "minuut",
	"second": "seconde",
	"showBackImage": "Achtergrondafbeelding weergeven",
	"soundVolume": "Geluidseffectvolume",
	"language": "Taal",
	"usage1": "Wattageconversie van magnetronovens",
	"usage2": "Converteert kooktijden voor de magnetron op basis van het wattage van uw magnetron.",
	"usage3": "Hoewel schattingen van de kooktijd voor magnetrons op de voedselverpakking kunnen staan, kunnen er gevallen zijn waarin het wattage van uw magnetron niet overeenkomt. In dergelijke gevallen wordt de juiste kooktijd berekend en weergegeven door het wattage om te rekenen.",
	"usage4": "Opmerking: cijfers zijn niet noodzakelijkerwijs nauwkeurig.",

	"dummy": "dummy"
}

lib/l10n/app_pl.arb

{
	"@@locale":"pl",
	"@locale": {
		"description": "ポーランド"
	},
	"title": "Konwersja mocy kuchenki mikrofalowej",
	"setting": "Ustawienie",
	"wattFrom": "Określona moc",
	"wattTo": "Docelowa moc",
	"fromMinute": "Określona minuta",
	"fromSecond": "określone jako drugie",
	"specified": "Określony",
	"conversion": "Konwersja",
	"minute": "minuta",
	"second": "drugi",
	"showBackImage": "Pokaż obraz tła",
	"soundVolume": "Głośność efektu dźwiękowego",
	"language": "Język",
	"usage1": "Konwersja mocy kuchenki mikrofalowej",
	"usage2": "Przelicza czas gotowania w kuchence mikrofalowej na podstawie mocy kuchenki mikrofalowej.",
	"usage3": "Chociaż szacunkowy czas gotowania w kuchence mikrofalowej może być podany na opakowaniach żywności, w niektórych przypadkach może się zdarzyć, że moc Twojej kuchenki mikrofalowej będzie się różnić.W takich przypadkach oblicza i wyświetla odpowiedni czas gotowania poprzez przeliczenie mocy.",
	"usage4": "Uwaga: Liczby niekoniecznie są dokładne.",

	"dummy": "dummy"
}

lib/l10n/app_pt.arb

{
	"@@locale":"pt",
	"@locale": {
		"description": "ポルトガル"
	},
	"title": "Conversão de potência do forno de microondas",
	"setting": "Contexto",
	"wattFrom": "Potência especificada",
	"wattTo": "Potência alvo",
	"fromMinute": "Minuto especificado",
	"fromSecond": "segundo especificado",
	"specified": "Especificadas",
	"conversion": "Conversão",
	"minute": "minuto",
	"second": "segundo",
	"showBackImage": "Mostrar imagem de fundo",
	"soundVolume": "Volume do efeito sonoro",
	"language": "Linguagem",
	"usage1": "Conversão de potência do forno de microondas",
	"usage2": "Converte os tempos de cozimento do micro-ondas com base na potência do seu forno micro-ondas.",
	"usage3": "Embora as estimativas de tempo de cozimento para fornos de micro-ondas possam ser fornecidas nas embalagens de alimentos, pode haver casos em que a potência do seu forno de micro-ondas não corresponda. Nesses casos, ele calcula e exibe o tempo de cozimento apropriado convertendo a potência.",
	"usage4": "Nota: Os números não são necessariamente precisos.",

	"dummy": "dummy"
}

lib/l10n/app_ro.arb

{
	"@@locale":"ro",
	"@locale": {
		"description": "ルーマニア"
	},
	"title": "Conversia puterii cuptorului cu microunde",
	"setting": "Setare",
	"wattFrom": "Puterea specificată",
	"wattTo": "Puterea țintă",
	"fromMinute": "Minut specificat",
	"fromSecond": "secunde specificate",
	"specified": "Specificat",
	"conversion": "Conversie",
	"minute": "minut",
	"second": "al doilea",
	"showBackImage": "Afișați imaginea de fundal",
	"soundVolume": "Volumul efectului sonor",
	"language": "Limba",
	"usage1": "Conversia puterii cuptorului cu microunde",
	"usage2": "Convertește timpii de gătire pentru cuptorul cu microunde în funcție de puterea cuptorului cu microunde.",
	"usage3": "Deși estimările timpului de gătire pentru cuptoarele cu microunde pot fi furnizate pe ambalajele alimentelor, pot exista cazuri în care puterea cuptorului cu microunde nu se potrivește. În astfel de cazuri, acesta calculează și afișează timpul de gătire adecvat prin conversia puterii.",
	"usage4": "Notă: numerele nu sunt neapărat exacte.",

	"dummy": "dummy"
}

lib/l10n/app_ru.arb

{
	"@@locale":"ru",
	"@locale": {
		"description": "ロシア"
	},
	"title": "Преобразование мощности микроволновой печи",
	"setting": "Параметр",
	"wattFrom": "Указанная мощность",
	"wattTo": "Целевая мощность",
	"fromMinute": "Указанная минута",
	"fromSecond": "указанный второй",
	"specified": "Указано",
	"conversion": "Конверсия",
	"minute": "минута",
	"second": "второй",
	"showBackImage": "Показать фоновое изображение",
	"soundVolume": "Громкость звукового эффекта",
	"language": "Язык",
	"usage1": "Преобразование мощности микроволновой печи",
	"usage2": "Преобразует время приготовления в микроволновой печи в зависимости от мощности вашей микроволновой печи.",
	"usage3": "Хотя приблизительное время приготовления для микроволновых печей может быть указано на упаковке пищевых продуктов, могут быть случаи, когда мощность вашей микроволновой печи не совпадает.В таких случаях она рассчитывает и отображает соответствующее время приготовления путем преобразования мощности.",
	"usage4": "Примечание: цифры не обязательно точны.",

	"dummy": "dummy"
}

lib/l10n/app_sk.arb

{
	"@@locale":"sk",
	"@locale": {
		"description": "スロバキア"
	},
	"title": "Konverzia výkonu mikrovlnnej rúry",
	"setting": "Nastavenie",
	"wattFrom": "Špecifikovaný výkon",
	"wattTo": "Cieľový výkon",
	"fromMinute": "Uvedená minúta",
	"fromSecond": "špecifikovaný ako druhý",
	"specified": "Špecifikované",
	"conversion": "Konverzia",
	"minute": "minútu",
	"second": "druhý",
	"showBackImage": "Zobraziť obrázok na pozadí",
	"soundVolume": "Hlasitosť zvukových efektov",
	"language": "Jazyk",
	"usage1": "Konverzia výkonu mikrovlnnej rúry",
	"usage2": "Prevádza časy varenia pre mikrovlnnú rúru na základe výkonu vašej mikrovlnnej rúry.",
	"usage3": "Hoci odhady času varenia pre mikrovlnné rúry môžu byť uvedené na obale potravín, môžu nastať prípady, kedy sa výkon vašej mikrovlnnej rúry nezhoduje.V takých prípadoch vypočíta a zobrazí vhodný čas varenia prepočítaním výkonu.",
	"usage4": "Poznámka: Čísla nemusia byť nevyhnutne presné.",

	"dummy": "dummy"
}

lib/l10n/app_sv.arb

{
	"@@locale":"sv",
	"@locale": {
		"description": "スウェーデン"
	},
	"title": "Mikrovågsugns effektkonvertering",
	"setting": "Miljö",
	"wattFrom": "Angivet wattal",
	"wattTo": "Måleffekt",
	"fromMinute": "Angiven minut",
	"fromSecond": "angivna andra",
	"specified": "Specificerad",
	"conversion": "Omvandling",
	"minute": "minut",
	"second": "andra",
	"showBackImage": "Visa bakgrundsbild",
	"soundVolume": "Ljudeffektvolym",
	"language": "Språk",
	"usage1": "Mikrovågsugns effektkonvertering",
	"usage2": "Konverterar tillagningstider för mikrovågsugnen baserat på effekten på din mikrovågsugn.",
	"usage3": "Även om uppskattningar av tillagningstid för mikrovågsugnar kan finnas på livsmedelsförpackningar, kan det finnas tillfällen där effekten på din mikrovågsugn inte stämmer överens. I sådana fall beräknar och visar den lämplig tillagningstid genom att konvertera watttalet.",
	"usage4": "Obs! Siffrorna är inte nödvändigtvis korrekta.",

	"dummy": "dummy"
}

lib/l10n/app_th.arb

{
	"@@locale":"th",
	"@locale": {
		"description": "タイ"
	},
	"title": "การแปลงวัตต์เตาอบไมโครเวฟ",
	"setting": "การตั้งค่า",
	"wattFrom": "วัตต์ที่ระบุ",
	"wattTo": "วัตต์เป้าหมาย",
	"fromMinute": "นาทีที่กำหนด",
	"fromSecond": "ระบุวินาที",
	"specified": "ระบุไว้",
	"conversion": "การแปลง",
	"minute": "นาที",
	"second": "ที่สอง",
	"showBackImage": "แสดงภาพพื้นหลัง",
	"soundVolume": "ระดับเสียงเอฟเฟกต์",
	"language": "ภาษา",
	"usage1": "การแปลงวัตต์เตาอบไมโครเวฟ",
	"usage2": "แปลงเวลาในการปรุงอาหารสำหรับไมโครเวฟตามกำลังไฟของเตาไมโครเวฟของคุณ",
	"usage3": "แม้ว่าอาจมีการระบุเวลาโดยประมาณในการปรุงอาหารสำหรับเตาอบไมโครเวฟไว้บนบรรจุภัณฑ์อาหาร แต่อาจมีบางกรณีที่วัตต์ของเตาไมโครเวฟไม่ตรงกัน ในกรณีเช่นนี้ ระบบจะคำนวณและแสดงเวลาในการปรุงอาหารที่เหมาะสมโดยการแปลงกำลังไฟฟ้า",
	"usage4": "หมายเหตุ: ตัวเลขไม่จำเป็นต้องแม่นยำ",

	"dummy": "dummy"
}

lib/l10n/app_zh.arb

{
	"@@locale":"zh",
	"@locale": {
		"description": "中国"
	},
	"title": "微波炉功率转换",
	"setting": "环境",
	"wattFrom": "指定瓦数",
	"wattTo": "目标瓦数",
	"fromMinute": "指定分钟",
	"fromSecond": "指定第二个",
	"specified": "指定的",
	"conversion": "转换",
	"minute": "分钟",
	"second": "第二",
	"showBackImage": "显示背景图片",
	"soundVolume": "音效音量",
	"language": "语言",
	"usage1": "微波炉功率转换",
	"usage2": "根据微波炉的功率转换微波炉的烹饪时间。",
	"usage3": "虽然食品包装上可能会提供微波炉的预计烹饪时间,但也可能存在微波炉的瓦数不匹配的情况,在这种情况下,它会通过转换瓦数来计算并显示适当的烹饪时间。",
	"usage4": "注意:数字不一定准确。",

	"dummy": "dummy"
}