ソースコード source code

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

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

下記コードの最終ビルド日: 2025-03-09

pubspec.yaml

name: ramentimer
description: "Ramen Timer"
# 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.5+6

environment:
  sdk: ^3.8.0-148.0.dev

# 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
  shared_preferences: ^2.0.15
  just_audio: ^0.9.46
  flutter_svg: ^2.0.17
  google_mobile_ads: ^5.3.1
  flutter_localizations:    #多言語ライブラリの本体    # .arbファイルを更新したら flutter gen-l10n
    sdk: flutter
  intl: ^0.20.2   #多言語やフォーマッタなどの関連ライブラリ
  package_info_plus: ^8.3.0
  wakelock_plus: ^1.2.10    #スリープ防止

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.8

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_launcher_icons: ^0.14.3    #flutter pub run flutter_launcher_icons
  flutter_native_splash: ^2.3.2     #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: ^5.0.0

flutter_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: '#ffcd40'
  image: 'assets/image/splash.png'
  color_dark: '#ffcd40'
  image_dark: 'assets/image/splash.png'
  fullscreen: true
  android_12:
    icon_background_color: '#ffcd40'
    image: 'assets/image/splash.png'
    icon_background_color_dark: '#ffcd40'
    image_dark: 'assets/image/splash.png'

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

# 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/sound/
    - assets/icon/
    - assets/image/

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

  # For details regarding adding assets from package dependencies, see
  # https://flutter.dev/to/asset-from-package

  # 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/to/font-from-package

lib/ad_manager.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:ramentimer/ad_unit_id.dart';

class AdManager {

  BannerAd? _bannerAd;
  BannerAd? get bannerAd => _bannerAd;

  Future<void> loadBannerAd(VoidCallback onAdLoaded) async {
    try {
      BannerAd bannerAd = BannerAd(
        adUnitId: AdUnitId.bannerAdUnitId,
        request: AdRequest(),
        size: AdSize.banner,
        listener: BannerAdListener(
          onAdLoaded: (ad) {
            _bannerAd = ad as BannerAd;
            onAdLoaded();
          },
          onAdFailedToLoad: (ad, err) {
            ad.dispose();
            onAdLoaded();
            //debugPrint('Failed to load a banner ad: $err');
          },
        ),
      );
      await bannerAd.load();
    } catch (e) {
      onAdLoaded();
      //debugPrint('Error loading banner ad: $e');
    }
  }

  Widget widget() {
    if (_bannerAd != null) {
      return Padding(
          padding: const EdgeInsets.only(top: 10, left: 0, right: 0, bottom: 0),
          child: Align(
            alignment: Alignment.topCenter,
            child: SizedBox(
              width: _bannerAd!.size.width.toDouble(),
              height: _bannerAd!.size.height.toDouble(),
              child: AdWidget(ad: _bannerAd!),
            ),
          )
      );
    } else {
      return Container();
    }
  }

  void dispose() {
    _bannerAd?.dispose();
  }

}

lib/ad_unit_id.dart

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

import 'dart:io';

class AdUnitId {

  static String get bannerAdUnitId {
    if (Platform.isAndroid) {
      //return 'ca-app-pub-3940256099942544/6300978111';  //test
      return '<YOUR_ANDROID_INTERSTITIAL_AD_UNIT_ID>';
    } else if (Platform.isIOS) {
      //return 'ca-app-pub-3940256099942544/2934735716';  //test
      return '<YOUR_ANDROID_INTERSTITIAL_AD_UNIT_ID>';
    } else {
      throw UnsupportedError('Unsupported platform');
    }
  }

  static String get interstitialAdUnitId {
    if (Platform.isAndroid) {
      //return 'ca-app-pub-3940256099942544/1033173712';  //test
      return '<YOUR_ANDROID_INTERSTITIAL_AD_UNIT_ID>';
    } else if (Platform.isIOS) {
      //return 'ca-app-pub-3940256099942544/4411468910';  //test
      return '<YOUR_IOS_INTERSTITIAL_AD_UNIT_ID>';
    } else {
      throw UnsupportedError('Unsupported platform');
    }
  }

  static String get rewardedAdUnitId {
    if (Platform.isAndroid) {
      //return 'ca-app-pub-3940256099942544/5224354917';  //test
      return '<YOUR_ANDROID_REWARDED_AD_UNIT_ID>';
    } else if (Platform.isIOS) {
      //return 'ca-app-pub-3940256099942544/1712485313';  //test
      return '<YOUR_IOS_REWARDED_AD_UNIT_ID>';
    } else {
      throw UnsupportedError('Unsupported platform');
    }
  }
}

lib/app_condition.dart

///
/// instant cup ramen timer
///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2022-06-27
///
library;

import 'package:flutter/material.dart';

import 'package:ramentimer/color_design.dart';

class AppCondition {
  static const int ready = 0;
  static const int complete = 1;
  int _gameCondition = 0;
  AppCondition() { //constructor
    _gameCondition = ready;
  }
  int getGameCondition() {
    return _gameCondition;
  }
  void setGameCondition(int cond) {
    _gameCondition = cond;
  }
  Color stageColor() {
    if (_gameCondition == ready) {
      return ColorDesign.canvasClose;
    } else if (_gameCondition == complete) {
      return ColorDesign.canvasOpen;
    }
    return ColorDesign.appBody;
  }
  Color bgColor() {
    if (_gameCondition == ready) {
      return ColorDesign.appBody;
    } else if (_gameCondition == complete) {
      return ColorDesign.canvasOpen;
    }
    return ColorDesign.appBody;
  }
}

lib/audio_play.dart

///
/// instant cup ramen timer
///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2022-06-27
///
library;

import 'l10n/app_localizations.dart';
import 'package:just_audio/just_audio.dart';

class AudioPlay {
  static const int soundOff = 1;
  static const int soundOn = 2;
  final String _audioStart = 'assets/sound/start.mp3';
  final String _audioStop = 'assets/sound/stop.mp3';
  final String _audioPushUp = 'assets/sound/push1.mp3';
  final String _audioPushDown = 'assets/sound/push2.mp3';
  final String _audioComplete = 'assets/sound/niwatori.mp3';
  static final List<AudioPlayer> _audioPlayerStart = [
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
  ];
  static final List<AudioPlayer> _audioPlayerStop = [
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
  ];
  static final List<AudioPlayer> _audioPlayerPushUp = [
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
  ];
  static final List<AudioPlayer> _audioPlayerPushDown = [
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
  ];
  static final List<AudioPlayer> _audioPlayerComplete = [
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
    AudioPlayer(),
  ];
  int _sound = soundOn;
  int _audioPlayerStartPtr = 0;
  int _audioPlayerStopPtr = 0;
  int _audioPlayerPushUpPtr = 0;
  int _audioPlayerPushDownPtr = 0;
  int _audioPlayerCompletePtr = 0;
  AudioPlay() { //constructor
    constructor();
  }
  void constructor() async {
    for (int i = 0; i < _audioPlayerStart.length; i++) {
      await _audioPlayerStart[i].setAsset(_audioStart);
    }
    for (int i = 0; i < _audioPlayerStop.length; i++) {
      await _audioPlayerStop[i].setAsset(_audioStop);
    }
    for (int i = 0; i < _audioPlayerPushUp.length; i++) {
      await _audioPlayerPushUp[i].setAsset(_audioPushUp);
    }
    for (int i = 0; i < _audioPlayerPushDown.length; i++) {
      await _audioPlayerPushDown[i].setAsset(_audioPushDown);
    }
    for (int i = 0; i < _audioPlayerComplete.length; i++) {
      await _audioPlayerComplete[i].setAsset(_audioComplete);
    }
  }
  void dispose() {
    for (int i = 0; i < _audioPlayerStart.length; i++) {
      _audioPlayerStart[i].dispose();
    }
    for (int i = 0; i < _audioPlayerStop.length; i++) {
      _audioPlayerStop[i].dispose();
    }
    for (int i = 0; i < _audioPlayerPushUp.length; i++) {
      _audioPlayerPushUp[i].dispose();
    }
    for (int i = 0; i < _audioPlayerPushDown.length; i++) {
      _audioPlayerPushDown[i].dispose();
    }
    for (int i = 0; i < _audioPlayerComplete.length; i++) {
      _audioPlayerComplete[i].dispose();
    }
  }
  void setSoundMode(int soundMode) {
    _sound = soundMode;
  }
  int getSoundMode() {
    return _sound;
  }
  String getSoundModeStr(dynamic context) {
    if (_sound == soundOff) {
      return AppLocalizations.of(context)!.off;
    } else if (_sound == soundOn) {
      return AppLocalizations.of(context)!.on;
    }
    return '';
  }
  void playSoundStart() async {
    if (_sound != soundOn) {
      return;
    }
    _audioPlayerStartPtr += 1;
    if (_audioPlayerStartPtr >= _audioPlayerStart.length) {
      _audioPlayerStartPtr = 0;
    }
    await _audioPlayerStart[_audioPlayerStartPtr].pause();
    await _audioPlayerStart[_audioPlayerStartPtr].seek(Duration.zero);
    await _audioPlayerStart[_audioPlayerStartPtr].play();
  }
  void playSoundStop() async {
    if (_sound != soundOn) {
      return;
    }
    _audioPlayerStopPtr += 1;
    if (_audioPlayerStopPtr >= _audioPlayerStop.length) {
      _audioPlayerStopPtr = 0;
    }
    await _audioPlayerStop[_audioPlayerStopPtr].pause();
    await _audioPlayerStop[_audioPlayerStopPtr].seek(Duration.zero);
    await _audioPlayerStop[_audioPlayerStopPtr].play();
  }
  void playSoundPushUp() async {
    if (_sound != soundOn) {
      return;
    }
    _audioPlayerPushUpPtr += 1;
    if (_audioPlayerPushUpPtr >= _audioPlayerPushUp.length) {
      _audioPlayerPushUpPtr = 0;
    }
    await _audioPlayerPushUp[_audioPlayerPushUpPtr].pause();
    await _audioPlayerPushUp[_audioPlayerPushUpPtr].seek(Duration.zero);
    await _audioPlayerPushUp[_audioPlayerPushUpPtr].play();
  }
  void playSoundPushDown() async {
    if (_sound != soundOn) {
      return;
    }
    _audioPlayerPushDownPtr += 1;
    if (_audioPlayerPushDownPtr >= _audioPlayerPushDown.length) {
      _audioPlayerPushDownPtr = 0;
    }
    await _audioPlayerPushDown[_audioPlayerPushDownPtr].pause();
    await _audioPlayerPushDown[_audioPlayerPushDownPtr].seek(Duration.zero);
    await _audioPlayerPushDown[_audioPlayerPushDownPtr].play();
  }
  void playSoundComplete() async {
    if (_sound != soundOn) {
      return;
    }
    _audioPlayerCompletePtr += 1;
    if (_audioPlayerCompletePtr >= _audioPlayerComplete.length) {
      _audioPlayerCompletePtr = 0;
    }
    await _audioPlayerComplete[_audioPlayerCompletePtr].pause();
    await _audioPlayerComplete[_audioPlayerCompletePtr].seek(Duration.zero);
    await _audioPlayerComplete[_audioPlayerCompletePtr].play();
  }
}

lib/color_design.dart

///
/// instant cup ramen timer
///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2022-06-27
///
library;

import 'package:flutter/material.dart';

class ColorDesign {
  static const Color appBackground = Color.fromARGB(255, 87,81,32);
  static const Color appHeader = Color.fromARGB(255, 138, 118, 51);
  static const Color appHeaderLine = Color.fromARGB(255, 158, 133, 52);
  static const Color appHeaderText = Color.fromARGB(255, 255, 255, 255);
  static const Color appBody = Color.fromARGB(255, 255, 255, 255);
  static const Color canvasClose = Color.fromARGB(255, 255, 255, 255);
  static const Color canvasOpen = Color.fromARGB(255,243,51,41);
}

lib/language_choice.dart

///
/// instant cup ramen timer
///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2022-06-27
///
library;

import 'package:flutter/material.dart';

class LanguageChoice {
  final Map<String,String> langMap = {
    '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': '中文',
  };
  List<String> languageList() {
    List<String> languages = [];
    langMap.forEach((key, value) {
      languages.add(key);
    });
    return languages;
  }
  String getLanguageName(String str) {
    if (langMap.containsKey(str)) {
      return langMap[str]!;
    }
    return '';
  }
  List<Locale> localeList() {
    List<Locale> locales = [];
    langMap.forEach((key, value) {
      locales.add(Locale(key));
    });
    return locales;
  }
}

lib/main.dart

///
/// instant cup ramen timer
///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2022-06-27
///
library;

import 'dart:async';
import 'l10n/app_localizations.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:wakelock_plus/wakelock_plus.dart';

import 'package:ramentimer/pref.dart';
import 'package:ramentimer/language_choice.dart';
import 'package:ramentimer/color_design.dart';
import 'package:ramentimer/ramen_image.dart';
import 'package:ramentimer/ramen_tick_timer.dart';
import 'package:ramentimer/app_condition.dart';
import 'package:ramentimer/ad_manager.dart';
import 'package:ramentimer/audio_play.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp, //縦固定
  ]);
  MobileAds.instance.initialize();
  runApp(const MainApp());
}

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

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

class _MainAppState extends State<MainApp> {
  Locale locale = AppLocalizations.supportedLocales.first;
  @override
  Widget build(BuildContext context) {
    final LanguageChoice languageChoice = LanguageChoice();
    final List<Locale> localeList = languageChoice.localeList();
    return MaterialApp(
      debugShowCheckedModeBanner: false,  //debug文字非表示
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: localeList,
      locale: locale,
      home: const MainPage(),
    );
  }
}

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

class _MainPageState extends State<MainPage> {
  final GlobalKey<ScaffoldState> _key = GlobalKey<ScaffoldState>();
  final AppCondition appCondition = AppCondition();
  final AdManager _adManager = AdManager();
  final AudioPlay audioPlay = AudioPlay();
  final RamenImage ramenImage = RamenImage();
  final RamenTickTimer ramenTickTimer = RamenTickTimer();
  String _version = '';
  @override
  void initState() {
    super.initState();
    _getVersion();
    _adManager.loadBannerAd(() {
      setState(() {});
    });
    _loadTimerCounter();
    _ramenTickTimerStart();
    _loadSound();
    _loadLanguage();
    WakelockPlus.enable();
  }

  @override
  void dispose() {
    WakelockPlus.disable();
    _adManager.dispose();
    audioPlay.dispose();
    super.dispose();
  }

  Future _getVersion() async {
    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    setState(() {
      _version = packageInfo.version;
    });
  }

  void _ramenTickTimerStart() {
    Timer.periodic(
      const Duration(seconds: 1), (Timer timer) {
        if (ramenTickTimer.getIsActive()) {
          ramenTickTimer.addTimerCounter(-1);
          final int timerCounter = ramenTickTimer.getTimerCounter();
          if (timerCounter > 0) {
            setState(() {
              appCondition.setGameCondition(AppCondition.ready);
            });
          } else {
            if (timerCounter == 0) {
              audioPlay.playSoundComplete();
            }
            setState(() {
              appCondition.setGameCondition(AppCondition.complete);
            });
          }
        }
      },
    );
  }
  void _loadLanguage() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final String lang = prefs.getString(Pref.keyLanguage) ?? 'en';
    if (!mounted) {
      return;
    }
    context.findAncestorStateOfType<_MainAppState>()!
      ..locale = Locale(lang)
      ..setState(() {});
  }
  void _saveLanguage(String lang) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString(Pref.keyLanguage, lang);
  }
  void _loadSound() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    audioPlay.setSoundMode(prefs.getInt(Pref.keySound) ?? AudioPlay.soundOn);
  }
  void _saveSound() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setInt(Pref.keySound, audioPlay.getSoundMode());
  }
  void _loadTimerCounter() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    setState(() {
      ramenTickTimer.setTimerCounter(prefs.getInt(Pref.keyTimerCounter) ?? 180);
    });
  }
  void _saveTimerCounter() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setInt(Pref.keyTimerCounter, ramenTickTimer.getTimerCounter());
  }
  void _onClickMinuteButton(int minute) {
    audioPlay.playSoundStart();
    setState(() {
      ramenTickTimer.setTimerCounter(minute * 60);
    });
    _saveTimerCounter();
  }
  void _onClickSecondButton(int second) {
    if (second > 0) {
      audioPlay.playSoundPushUp();
    } else {
      audioPlay.playSoundPushDown();
    }
    setState(() {
      ramenTickTimer.addTimerCounter(second);
    });
  }
  void _onClickStopButton() {
    audioPlay.playSoundStop();
    ramenTickTimer.stop();
  }
  void _onClickStartButton() {
    audioPlay.playSoundStart();
    ramenTickTimer.resume();
  }

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

  Widget _startOneButton() {
    return Expanded(
      child: ElevatedButton(
        onPressed: () {
          _onClickMinuteButton(1);
        },
        style: ElevatedButton.styleFrom(
          elevation: 0,
          backgroundColor: ColorDesign.appHeader,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0.0)),
          side: const BorderSide(width: 0.5, color: ColorDesign.appHeaderLine),
          padding: const EdgeInsets.symmetric(
            horizontal: 0,
            vertical: 24,
          ),
        ),
        child: Text(AppLocalizations.of(context)!.min1, style: const TextStyle(color: ColorDesign.appHeaderText)),
      )
    );
  }
  Widget _startTwoButton() {
    return Expanded(
      child: ElevatedButton(
        onPressed: () {
          _onClickMinuteButton(2);
        },
        style: ElevatedButton.styleFrom(
          elevation: 0,
          backgroundColor: ColorDesign.appHeader,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0.0)),
          side: const BorderSide(width: 0.5, color: ColorDesign.appHeaderLine),
          padding: const EdgeInsets.symmetric(
            horizontal: 0,
            vertical: 24,
          ),
        ),
        child: Text(AppLocalizations.of(context)!.min2, style: const TextStyle(color: ColorDesign.appHeaderText)),
      )
    );
  }
  Widget _startThreeButton() {
    return Expanded(
      child: ElevatedButton(
        onPressed: () {
          _onClickMinuteButton(3);
        },
        style: ElevatedButton.styleFrom(
          elevation: 0,
          backgroundColor: ColorDesign.appHeader,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0.0)),
          side: const BorderSide(width: 0.5, color: ColorDesign.appHeaderLine),
          padding: const EdgeInsets.symmetric(
            horizontal: 0,
            vertical: 24,
          ),
        ),
        child: Text(AppLocalizations.of(context)!.min3, style: const TextStyle(color: ColorDesign.appHeaderText)),
      )
    );
  }
  Widget _startFourButton() {
    return Expanded(
      child: ElevatedButton(
        onPressed: () {
          _onClickMinuteButton(4);
        },
        style: ElevatedButton.styleFrom(
          elevation: 0,
          backgroundColor: ColorDesign.appHeader,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0.0)),
          side: const BorderSide(width: 0.5, color: ColorDesign.appHeaderLine),
          padding: const EdgeInsets.symmetric(
            horizontal: 0,
            vertical: 24,
          ),
        ),
        child: Text(AppLocalizations.of(context)!.min4, style: const TextStyle(color: ColorDesign.appHeaderText)),
      )
    );
  }
  Widget _startFiveButton() {
    return Expanded(
      child: ElevatedButton(
        onPressed: () {
          _onClickMinuteButton(5);
        },
        style: ElevatedButton.styleFrom(
          elevation: 0,
          backgroundColor: ColorDesign.appHeader,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0.0)),
          side: const BorderSide(width: 0.5, color: ColorDesign.appHeaderLine),
          padding: const EdgeInsets.symmetric(
            horizontal: 0,
            vertical: 24,
          ),
        ),
        child: Text(AppLocalizations.of(context)!.min5, style: const TextStyle(color: ColorDesign.appHeaderText)),
      )
    );
  }
  Widget _startSixButton() {
    return Expanded(
      child: ElevatedButton(
        onPressed: () {
          _onClickMinuteButton(6);
        },
        style: ElevatedButton.styleFrom(
          elevation: 0,
          backgroundColor: ColorDesign.appHeader,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0.0)),
          side: const BorderSide(width: 0.5, color: ColorDesign.appHeaderLine),
          padding: const EdgeInsets.symmetric(
            horizontal: 0,
            vertical: 24,
          ),
        ),
        child: Text(AppLocalizations.of(context)!.min6, style: const TextStyle(color: ColorDesign.appHeaderText)),
      )
    );
  }
  Widget _minusButton() {
    return Expanded(
      child: ElevatedButton(
        onPressed: () {
          _onClickSecondButton(-10);
        },
        style: ElevatedButton.styleFrom(
          elevation: 0,
          backgroundColor: ColorDesign.appHeader,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0.0)),
          side: const BorderSide(width: 0.5, color: ColorDesign.appHeaderLine),
          padding: const EdgeInsets.symmetric(
            horizontal: 0,
            vertical: 24,
          ),
        ),
        child: Text(AppLocalizations.of(context)!.minus10sec, style: const TextStyle(color: ColorDesign.appHeaderText)),
      )
    );
  }
  Widget _plusButton() {
    return Expanded(
      child: ElevatedButton(
        onPressed: () {
          _onClickSecondButton(10);
        },
        style: ElevatedButton.styleFrom(
          elevation: 0,
          backgroundColor: ColorDesign.appHeader,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0.0)),
          side: const BorderSide(width: 0.5, color: ColorDesign.appHeaderLine),
          padding: const EdgeInsets.symmetric(
            horizontal: 0,
            vertical: 24,
          ),
        ),
        child: Text(AppLocalizations.of(context)!.plus10sec, style: const TextStyle(color: ColorDesign.appHeaderText)),
      )
    );
  }
  Widget _stopButton() {
    return Expanded(
      child: ElevatedButton(
        onPressed: _onClickStopButton,
        style: ElevatedButton.styleFrom(
          elevation: 0,
          backgroundColor: ColorDesign.appHeader,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0.0)),
          side: const BorderSide(width: 0.5, color: ColorDesign.appHeaderLine),
          padding: const EdgeInsets.symmetric(
            horizontal: 0,
            vertical: 24,
          ),
        ),
        child: Text(AppLocalizations.of(context)!.stop, style: const TextStyle(color: ColorDesign.appHeaderText)),
      )
    );
  }
  Widget _startButton() {
    return Expanded(
      child: ElevatedButton(
        onPressed: _onClickStartButton,
        style: ElevatedButton.styleFrom(
          elevation: 0,
          backgroundColor: ColorDesign.appHeader,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0.0)),
          side: const BorderSide(width: 0.5, color: ColorDesign.appHeaderLine),
          padding: const EdgeInsets.symmetric(
            horizontal: 0,
            vertical: 24,
          ),
        ),
        child: Text(AppLocalizations.of(context)!.resume, style: const TextStyle(color: ColorDesign.appHeaderText)),
      )
    );
  }
  Widget _dialogSound() {
    return SimpleDialog(
      title: Text('${AppLocalizations.of(context)!.sound}: ${audioPlay.getSoundModeStr(context)}'),
      children: <Widget>[
        SimpleDialogOption(
          child: Text(AppLocalizations.of(context)!.off),
          onPressed: () {
            setState(() {
              audioPlay.setSoundMode(AudioPlay.soundOff);
            });
            _saveSound();
            Navigator.pop(context);
          }
        ),
        SimpleDialogOption(
          child: Text(AppLocalizations.of(context)!.on),
          onPressed: () {
            setState(() {
              audioPlay.setSoundMode(AudioPlay.soundOn);
            });
            _saveSound();
            Navigator.pop(context);
          }
        ),
      ],
    );
  }
  Widget _dialogLanguage() {
    final LanguageChoice languageChoice = LanguageChoice();
    final List<String> langList = languageChoice.languageList();
    return SimpleDialog(
      title: Text(AppLocalizations.of(context)!.language),
      children: List.generate(langList.length,(index) {
        return SimpleDialogOption(
          child: Row(
            children:[
              SizedBox(
                width: 25,
                child: Text(langList[index])
              ),
              Text('- ${languageChoice.getLanguageName(langList[index])}')
            ]
          ),
          onPressed: () {
            _saveLanguage(langList[index]);
            context.findAncestorStateOfType<_MainAppState>()!
              ..locale = Locale(langList[index])
              ..setState((){});
            Navigator.pop(context);
          }
        );
      }),
    );
  }
  Widget _hamburgerMenu() {
    return Drawer(
      child: ListView(
        padding: EdgeInsets.zero,
        children: [
          SizedBox(
            //height: 190,
            child: DrawerHeader(
              decoration: const BoxDecoration(color: Colors.red),
              child: Column(children:[
                Row(children:[
                  SvgPicture.asset(RamenImage.close, width: 80, height: 96),
                  const SizedBox(width: 8),
                  Flexible(child: Text(AppLocalizations.of(context)!.appName,style: const TextStyle(color: Colors.white))),
                ]),
                Text(AppLocalizations.of(context)!.usage,style: const TextStyle(fontSize: 11,color: Colors.white)),
              ]),
            )
          ),
          ListTile(
            leading: const CircleAvatar(
              child: Icon(
                Icons.audiotrack,
              ),
            ),
            title: Text('${AppLocalizations.of(context)!.sound}: ${audioPlay.getSoundModeStr(context)}'),
            trailing: const Icon(
              Icons.arrow_circle_right_outlined,
            ),
            onTap: () {
              showDialog(
                context: context,
                barrierDismissible: true,
                builder: (_) {
                  return _dialogSound();
                }
              );
            },
          ),
          Container(
            padding: const EdgeInsets.only(left: 15,right: 15,bottom: 20),
            child: Text(AppLocalizations.of(context)!.sound1,style: const TextStyle(fontSize: 11,color: Colors.black54)),
          ),
          ListTile(
            leading: const CircleAvatar(
              child: Icon(
                Icons.language,
              ),
            ),
            title: Text(AppLocalizations.of(context)!.language),
            trailing: const Icon(
              Icons.arrow_circle_right_outlined,
            ),
            onTap: () {
              showDialog(
                context: context,
                barrierDismissible: true,
                builder: (_) {
                  return _dialogLanguage();
                }
              );
            },
          ),
          Container(
            padding: const EdgeInsets.only(left: 15,right: 15,top: 50),
            child: Text('v $_version',style: const TextStyle(fontSize: 11,color: Colors.black45)),
          ),
        ],
      ),
    );
  }
  Widget _settingButton() {
    return IconButton(
      icon: const Icon(Icons.menu,color: ColorDesign.appHeaderText),
      tooltip: AppLocalizations.of(context)!.setting,
      onPressed: () {
        _key.currentState?.openDrawer();
      },
    );
  }
  Widget _menuBar() {
    return Container(
      decoration: const BoxDecoration(color: ColorDesign.appHeader),
      child: Column(children: <Widget> [
        Row(children: <Widget> [
          _startOneButton(),
          _startTwoButton(),
          _startThreeButton(),
          _startFourButton(),
          _startFiveButton(),
          _startSixButton(),
        ]),
        Row(children: <Widget> [
          _minusButton(),
          _plusButton(),
          _stopButton(),
          _startButton(),
          _settingButton(),
        ]),
      ]),
    );
  }
  Widget _boxCanvas() {
    final String ramenImageStr = (ramenTickTimer.getTimerCounter() <= 0) ? ramenImage.getImageStr(true) : ramenImage.getImageStr(false);
    final String timeStr = ramenTickTimer.getTimeStr();
    return Stack(
      children: [
        SvgPicture.asset(
          ramenImageStr,
          semanticsLabel: 'ramen',
          width: double.infinity,
          height: double.infinity,
        ),
        AspectRatio(
          aspectRatio: 1 / 1,
          child: Container(
            alignment: Alignment.center,
            child: FractionallySizedBox(
              widthFactor: 0.26,
              child: FittedBox(
                fit: BoxFit.fitWidth,
                child: Text(timeStr, style: const TextStyle(fontSize: 100, fontWeight: FontWeight.w900, color: Colors.yellow)),
              ),
            ),
          ),
        ),
      ]
    );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _key,
      appBar: null,
      drawer: _hamburgerMenu(),
      backgroundColor: ColorDesign.appBackground,
      body: SafeArea(
        child: Center(
          child: Column(
            children: [
              _menuBar(),
              Expanded(
                child: Container(
                  color: appCondition.bgColor(),
                  padding: const EdgeInsets.only(top: 0, left: 8, right: 8, bottom: 10),
                  child: Center(
                    child: AspectRatio(
                      aspectRatio: 1 / 1.3,
                      child: Container(
                        width: double.infinity,
                        height: double.infinity,
                        color: appCondition.stageColor(),
                        child: _boxCanvas(),
                      ),
                    ),
                  ),
                ),
              ),
              //広告
              _adManager.widget()
            ]
          ),
        ),
      ),
    );
  }
}

lib/pref.dart

///
/// instant cup ramen timer
///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2022-06-27
///
///
library;

class Pref {
  static const String keyTimerCounter = "keyTimerCounter";
  static const String keySound = "keySound";
  static const String keyLanguage = "keyLanguage";
}

lib/ramen_image.dart

///
/// instant cup ramen timer
///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2022-06-27
///
library;

class RamenImage {
  static const String close = 'assets/image/cupramen_close.svg';
  static const String open = 'assets/image/cupramen_open.svg';
  String getImageStr(bool openClose) {
    if (openClose) {
      return open;
    }
    return close;
  }
}

lib/ramen_tick_timer.dart

///
/// instant cup ramen timer
///
/// @author akira ohmachi
/// @copyright ao-system, Inc.
/// @date 2022-06-27
///
library;

class RamenTickTimer {
  int _timerCounter = 180;
  bool _isTimerActive = true;
  void stop() {
    _isTimerActive = false;
  }
  void resume() {
    _isTimerActive = true;
  }
  bool getIsActive() {
    return _isTimerActive;
  }
  void setTimerCounter(int sec) {
    _timerCounter = sec;
  }
  int getTimerCounter() {
    return _timerCounter;
  }
  void addTimerCounter(int sec) {
    _timerCounter += sec;
  }
  String getTimeStr() {
    if (_timerCounter> 0) {
      int minute = (_timerCounter / 60).floor();
      int second = (_timerCounter % 60);
      return '$minute:${second.toString().padLeft(2,'0')}';
    } else {
      final int counter = _timerCounter * -1;
      int minute = (counter / 60).floor();
      int second = (counter % 60);
      return '-$minute:${second.toString().padLeft(2,'0')}';
    }
  }
}

lib/l10n/app_bg.arb

{
  "@@locale":"bg",
  "appName": "Таймер за незабавна чаша рамен",
  "min1": "1 м",
  "min2": "2 м",
  "min3": "3 м",
  "min4": "4 м",
  "min5": "5 м",
  "min6": "6 м",
  "minus10sec": "-10 сек",
  "plus10sec": "+10 сек",
  "stop": "Спри се",
  "resume": "Продължи",
  "setting": "настройка",
  "sound": "звук",
  "sound1": "Звуков ефект от операцията",
  "on": "НА",
  "off": "ИЗКЛ",
  "language": "език",
  "usage": "Отброяването ще започне веднага след като стартирате приложението"
}

lib/l10n/app_cs.arb

{
  "@@locale":"cs",
  "appName": "Časovač ramen na instantní šálek",
  "min1": "1 min",
  "min2": "2 min",
  "min3": "3 min",
  "min4": "4 min",
  "min5": "5 min",
  "min6": "6 min",
  "minus10sec": "-10 sek",
  "plus10sec": "+10 sek",
  "stop": "Stop",
  "resume": "Životopis",
  "setting": "nastavení",
  "sound": "zvuk",
  "sound1": "Provozní zvukový efekt",
  "on": "NA",
  "off": "OFF",
  "language": "Jazyk",
  "usage": "Odpočítávání začne, jakmile aplikaci spustíte"
}

lib/l10n/app_da.arb

{
  "@@locale":"da",
  "appName": "Øjeblikkelig kop ramen timer",
  "min1": "1 min",
  "min2": "2 min",
  "min3": "3 min",
  "min4": "4 min",
  "min5": "5 min",
  "min6": "6 min",
  "minus10sec": "-10 sek",
  "plus10sec": "+10 sek",
  "stop": "Hold op",
  "resume": "Genoptag",
  "setting": "indstilling",
  "sound": "lyd",
  "sound1": "Operation lydeffekt",
  "on": "PÅ",
  "off": "FRA",
  "language": "Sprog",
  "usage": "Nedtællingen starter, så snart du starter appen"
}

lib/l10n/app_de.arb

{
  "@@locale":"de",
  "appName": "Instant-Cup-Ramen-Timer",
  "min1": "1 Min",
  "min2": "2 Min",
  "min3": "3 Min",
  "min4": "4 Min",
  "min5": "5 Min",
  "min6": "6 Min",
  "minus10sec": "-10 Sek",
  "plus10sec": "+10 Sek",
  "stop": "Halt",
  "resume": "Fortsetzen",
  "setting": "Einstellung",
  "sound": "Klang",
  "sound1": "Betriebsgeräuscheffekt",
  "on": "AN",
  "off": "AUS",
  "language": "Sprache",
  "usage": "Der Countdown beginnt, sobald Sie die App starten"
}

lib/l10n/app_el.arb

{
  "@@locale":"el",
  "appName": "Στιγμιαίος χρονοδιακόπτης ramen cup",
  "min1": "1 λεπ",
  "min2": "2 λεπ",
  "min3": "3 λεπ",
  "min4": "4 λεπ",
  "min5": "5 λεπ",
  "min6": "6 λεπ",
  "minus10sec": "-10 δευ",
  "plus10sec": "+10 δευ",
  "stop": "Να",
  "resume": "αρχή",
  "setting": "σύνθεση",
  "sound": "ήχος",
  "sound1": "Ηχητικό εφέ λειτουργίας",
  "on": "ναι",
  "off": "Οχι",
  "language": "Γλώσσα",
  "usage": "Η αντίστροφη μέτρηση θα ξεκινήσει μόλις εκκινήσετε την εφαρμογή"
}

lib/l10n/app_en.arb

{
  "@@locale":"en",
  "appName": "Instant cup ramen timer",
  "min1": "1 min",
  "min2": "2 min",
  "min3": "3 min",
  "min4": "4 min",
  "min5": "5 min",
  "min6": "6 min",
  "minus10sec": "-10 sec",
  "plus10sec": "+10 sec",
  "stop": "Stop",
  "resume": "Resume",
  "setting": "Setting",
  "sound": "Sound",
  "sound1": "Operation sound effect",
  "on": "ON",
  "off": "OFF",
  "language": "Language",
  "usage": "The countdown will start as soon as you launch the app."
}

lib/l10n/app_es.arb

{
  "@@locale":"es",
  "appName": "Temporizador de ramen de taza instantánea",
  "min1": "1 min",
  "min2": "2 min",
  "min3": "3 min",
  "min4": "4 min",
  "min5": "5 min",
  "min6": "6 min",
  "minus10sec": "-10 segu",
  "plus10sec": "+10 segu",
  "stop": "Deténgase",
  "resume": "Reanudar",
  "setting": "ajuste",
  "sound": "sonido",
  "sound1": "Efecto de sonido de operación",
  "on": "EN",
  "off": "APAGADO",
  "language": "idioma",
  "usage": "La cuenta regresiva comenzará tan pronto como inicie la aplicación"
}

lib/l10n/app_et.arb

{
  "@@locale":"et",
  "appName": "Kiire tassi rameni taimer",
  "min1": "1 min",
  "min2": "2 min",
  "min3": "3 min",
  "min4": "4 min",
  "min5": "5 min",
  "min6": "6 min",
  "minus10sec": "-10 sek",
  "plus10sec": "+10 sek",
  "stop": "Peatus",
  "resume": "Jätka",
  "setting": "seadistus",
  "sound": "heli",
  "sound1": "Operatsiooni heliefekt",
  "on": "PEAL",
  "off": "VÄLJAS",
  "language": "keel",
  "usage": "Taimeroendus algab kohe pärast rakenduse käivitamist"
}

lib/l10n/app_fi.arb

{
  "@@locale":"fi",
  "appName": "Instant cup ramen ajastin",
  "min1": "1 min",
  "min2": "2 min",
  "min3": "3 min",
  "min4": "4 min",
  "min5": "5 min",
  "min6": "6 min",
  "minus10sec": "-10 sek",
  "plus10sec": "+10 sek",
  "stop": "Lopettaa",
  "resume": "Jatkaa",
  "setting": "asetusta",
  "sound": "ääni",
  "sound1": "Toiminnan äänitehoste",
  "on": "PÄÄLLÄ",
  "off": "POIS",
  "language": "Kieli",
  "usage": "Lähtölaskenta alkaa heti, kun käynnistät sovelluksen"
}

lib/l10n/app_fr.arb

{
  "@@locale":"fr",
  "appName": "Minuteur instantané de ramen de tasse",
  "min1": "1 min",
  "min2": "2 min",
  "min3": "3 min",
  "min4": "4 min",
  "min5": "5 min",
  "min6": "6 min",
  "minus10sec": "-10 sec",
  "plus10sec": "+10 sec",
  "stop": "Arrêt",
  "resume": "CV",
  "setting": "paramètre",
  "sound": "du son",
  "sound1": "Effet sonore d'opération",
  "on": "SUR",
  "off": "ARRÊT",
  "language": "Langue",
  "usage": "Le compte à rebours commencera dès que vous lancerez l'application"
}

lib/l10n/app_hu.arb

{
  "@@locale":"hu",
  "appName": "Azonnali csésze ramen időzítő",
  "min1": "1 per",
  "min2": "2 per",
  "min3": "3 per",
  "min4": "4 per",
  "min5": "5 per",
  "min6": "6 per",
  "minus10sec": "-10 más",
  "plus10sec": "+10 más",
  "stop": "Állj meg",
  "resume": "Önéletrajz",
  "setting": "beállítás",
  "sound": "hang",
  "sound1": "Működési hanghatás",
  "on": "TOVÁBB",
  "off": "KI",
  "language": "nyelv",
  "usage": "A visszaszámlálás azonnal elindul, amint elindítja az alkalmazást"
}

lib/l10n/app_it.arb

{
  "@@locale":"it",
  "appName": "Timer ramen per tazza istantaneo",
  "min1": "1 min",
  "min2": "2 min",
  "min3": "3 min",
  "min4": "4 min",
  "min5": "5 min",
  "min6": "6 min",
  "minus10sec": "-10 sec",
  "plus10sec": "+10 sec",
  "stop": "Fermare",
  "resume": "Riprendere",
  "setting": "ambientazione",
  "sound": "suono",
  "sound1": "Effetto sonoro dell'operazione",
  "on": "SU",
  "off": "SPENTO",
  "language": "linguaggio",
  "usage": "Il conto alla rovescia inizierà non appena avvierai l'app"
}

lib/l10n/app_ja.arb

{
  "@@locale":"ja",
  "appName": "インスタントカップラーメンタイマー",
  "min1": "1分",
  "min2": "2分",
  "min3": "3分",
  "min4": "4分",
  "min5": "5分",
  "min6": "6分",
  "minus10sec": "-10秒",
  "plus10sec": "+10秒",
  "stop": "停止",
  "resume": "再開",
  "setting": "設定",
  "sound": "音",
  "sound1": "操作による効果音",
  "on": "ON",
  "off": "OFF",
  "language": "言語",
  "usage": "アプリを起動するとすぐにカウントダウンが始まります。"
}

lib/l10n/app_lt.arb

{
  "@@locale":"lt",
  "appName": "Momentinis puodelio ramen laikmatis",
  "min1": "1 min",
  "min2": "2 min",
  "min3": "3 min",
  "min4": "4 min",
  "min5": "5 min",
  "min6": "6 min",
  "minus10sec": "-10 sek",
  "plus10sec": "+10 sek",
  "stop": "Sustabdyti",
  "resume": "Aprašymas",
  "setting": "nustatymą",
  "sound": "garsas",
  "sound1": "Operacijos garso efektas",
  "on": "ĮJUNGTA",
  "off": "IŠJUNGTA",
  "language": "kalba",
  "usage": "Atgalinis skaičiavimas prasidės iškart, kai tik paleisite programą"
}

lib/l10n/app_lv.arb

{
  "@@locale":"lv",
  "appName": "Tūlītēja kausa ramen taimeris",
  "min1": "1 min",
  "min2": "2 min",
  "min3": "3 min",
  "min4": "4 min",
  "min5": "5 min",
  "min6": "6 min",
  "minus10sec": "-10 sek",
  "plus10sec": "+10 sek",
  "stop": "Stop",
  "resume": "Turpināt",
  "setting": "iestatījumu",
  "sound": "skaņu",
  "sound1": "Operācijas skaņas efekts",
  "on": "IESL",
  "off": "IZSLĒGTS IZSL",
  "language": "valodu",
  "usage": "Atpakaļskaitīšana sāksies, tiklīdz palaižat lietotni"
}

lib/l10n/app_nl.arb

{
  "@@locale":"nl",
  "appName": "Instant kopje ramen-timer",
  "min1": "1 min",
  "min2": "2 min",
  "min3": "3 min",
  "min4": "4 min",
  "min5": "5 min",
  "min6": "6 min",
  "minus10sec": "-10 sec",
  "plus10sec": "+10 sec",
  "stop": "Hou op",
  "resume": "Cv",
  "setting": "instelling",
  "sound": "geluid",
  "sound1": "Operatie geluidseffect",
  "on": "AAN",
  "off": "UIT",
  "language": "taal",
  "usage": "Het aftellen begint zodra je de app start"
}

lib/l10n/app_pl.arb

{
  "@@locale":"pl",
  "appName": "Natychmiastowy czasomierz kubka ramen",
  "min1": "1 min",
  "min2": "2 min",
  "min3": "3 min",
  "min4": "4 min",
  "min5": "5 min",
  "min6": "6 min",
  "minus10sec": "-10 sek",
  "plus10sec": "+10 sek",
  "stop": "Zatrzymaj",
  "resume": "Wznawiać",
  "setting": "ustawienie",
  "sound": "dźwięk",
  "sound1": "Efekt dźwiękowy operacji",
  "on": "NA ",
  "off": "WYŁĄCZ",
  "language": "język",
  "usage": "Odliczanie rozpocznie się zaraz po uruchomieniu aplikacji"
}

lib/l10n/app_pt.arb

{
  "@@locale":"pt",
  "appName": "Temporizador de ramen de copo instantâneo",
  "min1": "1 min",
  "min2": "2 min",
  "min3": "3 min",
  "min4": "4 min",
  "min5": "5 min",
  "min6": "6 min",
  "minus10sec": "-10 seg",
  "plus10sec": "+10 seg",
  "stop": "Pare",
  "resume": "Retomar",
  "setting": "contexto",
  "sound": "som",
  "sound1": "Efeito sonoro de operação",
  "on": "SOBRE",
  "off": "DESLIGADO",
  "language": "Língua",
  "usage": "A contagem regressiva começará assim que você iniciar o aplicativo"
}

lib/l10n/app_ro.arb

{
  "@@locale":"ro",
  "appName": "Cronometru instantaneu pentru ramen",
  "min1": "1 min",
  "min2": "2 min",
  "min3": "3 min",
  "min4": "4 min",
  "min5": "5 min",
  "min6": "6 min",
  "minus10sec": "-10 sec",
  "plus10sec": "+10 sec",
  "stop": "Stop",
  "resume": "Relua",
  "setting": "setare",
  "sound": "sunet",
  "sound1": "Efect de sunet de operare",
  "on": "da",
  "off": "Nu",
  "language": "limba",
  "usage": "Numărătoarea inversă va începe imediat ce lansați aplicația"
}

lib/l10n/app_ru.arb

{
  "@@locale":"ru",
  "appName": "Таймер быстрого приготовления чашки рамен",
  "min1": "1 ми",
  "min2": "2 ми",
  "min3": "3 ми",
  "min4": "4 ми",
  "min5": "5 ми",
  "min6": "6 ми",
  "minus10sec": "-10 сек",
  "plus10sec": "+10 сек",
  "stop": "оста",
  "resume": "Продо",
  "setting": "параметр",
  "sound": "звук",
  "sound1": "Звуковой эффект операции",
  "on": "да",
  "off": "Нет",
  "language": "язык",
  "usage": "Обратный отсчет начнется, как только вы запустите приложение"
}

lib/l10n/app_sk.arb

{
  "@@locale":"sk",
  "appName": "Okamžitý časovač ramena šálky",
  "min1": "1 min",
  "min2": "2 min",
  "min3": "3 min",
  "min4": "4 min",
  "min5": "5 min",
  "min6": "6 min",
  "minus10sec": "-10 sek",
  "plus10sec": "+10 sek",
  "stop": "Stop",
  "resume": "začať",
  "setting": "nastavenie",
  "sound": "zvuk",
  "sound1": "Zvukový efekt prevádzky",
  "on": "Áno",
  "off": "Nie",
  "language": "Jazyk",
  "usage": "Odpočítavanie sa spustí hneď po spustení aplikácie"
}

lib/l10n/app_sv.arb

{
  "@@locale":"sv",
  "appName": "Omedelbar kopp ramen timer",
  "min1": "1 min",
  "min2": "2 min",
  "min3": "3 min",
  "min4": "4 min",
  "min5": "5 min",
  "min6": "6 min",
  "minus10sec": "-10 sek",
  "plus10sec": "+10 sek",
  "stop": "Sluta",
  "resume": "Återuppta",
  "setting": "miljö",
  "sound": "ljud",
  "sound1": "Operation ljudeffekt",
  "on": "ja",
  "off": "Nej",
  "language": "språk",
  "usage": "Nedräkningen startar så snart du startar appen"
}

lib/l10n/app_th.arb

{
  "@@locale":"th",
  "appName": "จับเวลาราเม็งถ้วยทันที",
  "min1": "1 นาที",
  "min2": "2 นาที",
  "min3": "3 นาที",
  "min4": "4 นาที",
  "min5": "5 นาที",
  "min6": "6 นาที",
  "minus10sec": "-10 วินาที",
  "plus10sec": "+10 วินาที",
  "stop": "หยุด",
  "resume": "ประวัติย่อ",
  "setting": "การตั้งค่า",
  "sound": "เสียง",
  "sound1": "เอฟเฟกต์เสียงการทำงาน",
  "on": "ใช่",
  "off": "ไม่",
  "language": "ภาษา",
  "usage": "การนับถอยหลังจะเริ่มขึ้นทันทีที่คุณเปิดแอป"
}

lib/l10n/app_zh.arb

{
  "@@locale":"zh",
  "appName": "速溶杯拉面计时器",
  "min1": "1分钟",
  "min2": "2分钟",
  "min3": "3分钟",
  "min4": "4 分钟",
  "min5": "5分钟",
  "min6": "6 分钟",
  "minus10sec": "-10 秒",
  "plus10sec": "+10 秒",
  "stop": "停止",
  "resume": "恢复",
  "setting": "环境",
  "sound": "声音",
  "sound1": "操作音效",
  "on": "是的",
  "off": "不",
  "language": "语",
  "usage": "倒计时将在您启动应用程序后立即开始"
}