diff --git a/android/app/build.gradle b/android/app/build.gradle index d24368ef..08ef8d71 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -52,42 +52,6 @@ android { } defaultConfig { - // Map for the version code that gives each ABI a value. - - // // For per-density APKs, create a similar map: - // // ext.densityCodes = ['mdpi': 1, 'hdpi': 2, 'xhdpi': 3] - - - // // For each APK output variant, override versionCode with a combination of - // // ext.abiCodes * 1000 + variant.versionCode. In this example, variant.versionCode - // // is equal to defaultConfig.versionCode. If you configure product flavors that - // // define their own versionCode, variant.versionCode uses that value instead. - // project.android.applicationVariants.all { variant -> - - // // Assigns a different version code for each output APK - // // other than the universal APK. - // variant.outputs.each { output -> - - // // Stores the value of ext.abiCodes that is associated with the ABI for this variant. - // def baseAbiVersionCode = - // // Determines the ABI for this variant and returns the mapped value. - // project.ext.abiCodes.get(output.getFilter(OutputFile.ABI)) - - // // Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes, - // // the following code doesn't override the version code for universal APKs. - // // However, because you want universal APKs to have the lowest version code, - // // this outcome is desirable. - // if (baseAbiVersionCode != null) { - - // // Assigns the new version code to versionCodeOverride, which changes the - // // version code for only the output APK, not for the variant itself. Skipping - // // this step causes Gradle to use the value of variant.versionCode for the APK. - // output.versionCodeOverride = - // variant.versionCode * 10 + baseAbiVersionCode - // } - // } - // } - applicationId "com.vicolo.chrono" minSdkVersion 21 targetSdkVersion flutter.targetSdkVersion @@ -155,7 +119,3 @@ flutter { source '../..' } -dependencies { - // implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - // -} diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 63cec568..07d76efd 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -126,5 +126,28 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/vicolo/chrono/AnalogueClockWidgetProvider.kt b/android/app/src/main/kotlin/com/vicolo/chrono/AnalogueClockWidgetProvider.kt new file mode 100644 index 00000000..eba3e283 --- /dev/null +++ b/android/app/src/main/kotlin/com/vicolo/chrono/AnalogueClockWidgetProvider.kt @@ -0,0 +1,79 @@ +package com.vicolo.chrono + +import android.app.PendingIntent +import android.appwidget.AppWidgetManager +import android.appwidget.AppWidgetProvider +import android.content.Context +import android.content.Intent +import android.widget.RemoteViews +// import es.antonborri.home_widget.HomeWidgetBackgroundIntent +// import es.antonborri.home_widget.HomeWidgetLaunchIntent +// import es.antonborri.home_widget.HomeWidgetProvider + +class AnalogueClockWidgetProvider : AppWidgetProvider() { + override fun onUpdate( + context: Context, + appWidgetManager: AppWidgetManager, + appWidgetIds: IntArray, + ) { // Perform this loop procedure for each widget that belongs to this + // provider. + appWidgetIds.forEach { appWidgetId -> + // Create an Intent to launch ExampleActivity. + // Open App on Widget Click + val views = + RemoteViews(context.packageName, R.layout.analogue_clock_widget).apply { + // Open App on Widget Click + val pendingIntent: PendingIntent = + PendingIntent.getActivity( + // context = + context, + // requestCode = + 0, + // intent = + Intent(context, MainActivity::class.java), + // flags = + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, + ) + // Swap Title Text by calling Dart Code in the Background + // setTextViewText(R.id.widget_title, widgetData.getString("title", null) + // ?: "No Title Set") + // val backgroundIntent = HomeWidgetBackgroundIntent.getBroadcast( + // context, + // Uri.parse("homeWidgetExample://titleClicked") + // ) + // setOnClickPendingIntent(R.id.widget_title, backgroundIntent) + // + // val message = widgetData.getString("message", null) + // setTextViewText(R.id.widget_message, message + // ?: "No Message Set") + // // Show Images saved with `renderFlutterWidget` + // val image = widgetData.getString("dashIcon", null) + // if (image != null) { + // setImageViewBitmap(R.id.widget_img, BitmapFactory.decodeFile(image)) + // setViewVisibility(R.id.widget_img, View.VISIBLE) + // } else { + // setViewVisibility(R.id.widget_img, View.GONE) + // } + // + // // Detect App opened via Click inside Flutter + // val pendingIntentWithData = HomeWidgetLaunchIntent.getActivity( + // context, + // MainActivity::class.java, + // Uri.parse("homeWidgetExample://message?message=$message")) + // setOnClickPendingIntent(R.id.widget_message, pendingIntentWithData) + } + // Get the layout for the widget and attach an onClick listener to + // the button. + // val views: RemoteViews = RemoteViews( + // context.packageName, + // R.layout.appwidget_provider_layout + // ).apply { + // setOnClickPendingIntent(R.id.button, pendingIntent) + // } + + // Tell the AppWidgetManager to perform an update on the current + // widget. + appWidgetManager.updateAppWidget(appWidgetId, views) + } + } +} diff --git a/android/app/src/main/kotlin/com/vicolo/chrono/DigitalClockDateWidgetProvider.kt b/android/app/src/main/kotlin/com/vicolo/chrono/DigitalClockDateWidgetProvider.kt new file mode 100644 index 00000000..03b9dd1f --- /dev/null +++ b/android/app/src/main/kotlin/com/vicolo/chrono/DigitalClockDateWidgetProvider.kt @@ -0,0 +1,91 @@ +package com.vicolo.chrono + +import android.app.PendingIntent +import android.appwidget.AppWidgetManager +import android.appwidget.AppWidgetProvider +import android.content.Context +import android.content.Intent +import android.widget.RemoteViews +import android.content.SharedPreferences +import es.antonborri.home_widget.HomeWidgetBackgroundIntent +import es.antonborri.home_widget.HomeWidgetLaunchIntent +import es.antonborri.home_widget.HomeWidgetProvider +import es.antonborri.home_widget.HomeWidgetPlugin +import android.util.Log + +class DigitalClockDateWidgetProvider : HomeWidgetProvider() { + override fun onUpdate( + context: Context, + appWidgetManager: AppWidgetManager, + appWidgetIds: IntArray, + widgetData: SharedPreferences, + ) { // Perform this loop procedure for each widget that belongs to this + // provider. + Log.d("TAG", "======================================YOO") + + appWidgetIds.forEach { appWidgetId -> + // Create an Intent to launch ExampleActivity. + // Open App on Widget Click + val views = + RemoteViews(context.packageName, R.layout.digital_clock_date_widget).apply { + // Open App on Widget Click + val pendingIntent: PendingIntent = + PendingIntent.getActivity( + // context = + context, + // requestCode = + 0, + // intent = + Intent(context, MainActivity::class.java), + // flags = + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, + ) + val dateFormat = widgetData.getString("dateFormat", "EEE, d MMM") + val timeFormat = widgetData.getString("timeFormat", "HH:mm") + setCharSequence (R.id.widget_text_clock, "setFormat24Hour", timeFormat) + setCharSequence (R.id.widget_text_clock, "setFormat12Hour", timeFormat) + setCharSequence (R.id.widget_date, "setFormat24Hour", dateFormat) + setCharSequence (R.id.widget_date, "setFormat12Hour", dateFormat) + // Swap Title Text by calling Dart Code in the Background + // setTextViewText(R.id.widget_title, widgetData.getString("title", null) + // ?: "No Title Set") + // val backgroundIntent = HomeWidgetBackgroundIntent.getBroadcast( + // context, + // Uri.parse("homeWidgetExample://titleClicked") + // ) + // setOnClickPendingIntent(R.id.widget_title, backgroundIntent) + // + // val message = widgetData.getString("message", null) + // setTextViewText(R.id.widget_message, message + // ?: "No Message Set") + // // Show Images saved with `renderFlutterWidget` + // val image = widgetData.getString("dashIcon", null) + // if (image != null) { + // setImageViewBitmap(R.id.widget_img, BitmapFactory.decodeFile(image)) + // setViewVisibility(R.id.widget_img, View.VISIBLE) + // } else { + // setViewVisibility(R.id.widget_img, View.GONE) + // } + // + // // Detect App opened via Click inside Flutter + // val pendingIntentWithData = HomeWidgetLaunchIntent.getActivity( + // context, + // MainActivity::class.java, + // Uri.parse("homeWidgetExample://message?message=$message")) + // setOnClickPendingIntent(R.id.widget_message, pendingIntentWithData) + } + // Get the layout for the widget and attach an onClick listener to + // the button. + // val views: RemoteViews = RemoteViews( + // context.packageName, + // R.layout.appwidget_provider_layout + // ).apply { + // setOnClickPendingIntent(R.id.button, pendingIntent) + // } + + // Tell the AppWidgetManager to perform an update on the current + // widget. + appWidgetManager.updateAppWidget(appWidgetId, views) + } + } +} diff --git a/android/app/src/main/kotlin/com/vicolo/chrono/DigitalClockWidgetProvider.kt b/android/app/src/main/kotlin/com/vicolo/chrono/DigitalClockWidgetProvider.kt new file mode 100644 index 00000000..0c5f0c7b --- /dev/null +++ b/android/app/src/main/kotlin/com/vicolo/chrono/DigitalClockWidgetProvider.kt @@ -0,0 +1,130 @@ +package com.vicolo.chrono + +import android.app.PendingIntent +import android.appwidget.AppWidgetManager +import android.content.Context +import android.content.Intent +import android.content.SharedPreferences +import android.util.Log +import android.widget.RemoteViews +import android.graphics.Color +import es.antonborri.home_widget.HomeWidgetProvider +import android.view.ViewGroup.LayoutParams +import android.view.View +import android.util.TypedValue + +class DigitalClockWidgetProvider : HomeWidgetProvider() { + override fun onUpdate( + context: Context, + appWidgetManager: AppWidgetManager, + appWidgetIds: IntArray, + widgetData: SharedPreferences, + ) { // Perform this loop procedure for each widget that belongs to this + // provider. + Log.d("TAG", "Updating Digital Clock Widget"); + + appWidgetIds.forEach { appWidgetId -> + // Create an Intent to launch ExampleActivity. + // Open App on Widget Click + val views = + RemoteViews(context.packageName, R.layout.digital_clock_widget).apply { + // Open App on Widget Click + val pendingIntent: PendingIntent = + PendingIntent.getActivity( + // context = + context, + // requestCode = + 0, + // intent = + Intent(context, MainActivity::class.java), + // flags = + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, + ) + val dateFormat = widgetData.getString("dateFormat", "EEE, d MMM") + val timeFormat = widgetData.getString("timeFormat", "HH:mm") + val dateSize = widgetData.getInt("dateSize", 25) + val timeSize = widgetData.getInt("timeSize", 100) + val textColor = widgetData.getString("textColor", "#FFFFFF") + // val shadowColor = widgetData.getString("shadowColor", "#000000") + // val shadowElevation = widgetData.getFloat("shadowElevation", 1.0f) + // val shadowBlur = widgetData.getFloat("shadowBlur", 1.0f) + val showDate = widgetData.getBoolean("showDate", true) + + setCharSequence(R.id.widget_text_clock, "setFormat24Hour", timeFormat) + setCharSequence(R.id.widget_text_clock, "setFormat12Hour", timeFormat) + setCharSequence(R.id.widget_date, "setFormat24Hour", "EEE, d MMM") + setCharSequence(R.id.widget_date, "setFormat12Hour", "EEE, d MMM") + setColorInt(R.id.widget_text_clock, "setTextColor", Color.parseColor(textColor), Color.parseColor(textColor)) + setColorInt(R.id.widget_date, "setTextColor", Color.parseColor(textColor), Color.parseColor(textColor)) + // setFloat(R.id.widget_text_clock, "setTextSize", timeSize.toFloat()) + // setFloat(R.id.widget_date, "setTextSize", dateSize.toFloat()) + setViewLayoutHeight(R.id.widget_text_clock, timeSize.toFloat(), TypedValue.COMPLEX_UNIT_SP) + setViewLayoutHeight(R.id.widget_date, dateSize.toFloat(), TypedValue.COMPLEX_UNIT_SP) + setViewVisibility(R.id.widget_date, if(showDate) View.VISIBLE else View.GONE) + // + // R.layout.digital_clock_widget.findViewById(R.id.widget_text_clock).apply { + // val param = + // LinearLayout.LayoutParams( + // LayoutParams.MATCH_PARENT, + // LayoutParams.MATCH_PARENT, + // timeSize, + // ) + // setLayoutParams(param) + // setShadowLayer(shadowBlur, 0f, shadowElevation, shadowColor) + // } + // + // R.layout.digital_clock_widget.findViewById(R.id.widget_date).apply { + // val param = + // LinearLayout.LayoutParams( + // LayoutParams.MATCH_PARENT, + // LayoutParams.MATCH_PARENT, + // dateSize, + // ) + // setLayoutParams(param) + // setTextColor(textColor) + // setShadowLayer(shadowBlur, 0f, shadowElevation, shadowColor) + // } + + // Swap Title Text by calling Dart Code in the Background + // setTextViewText(R.id.widget_title, widgetData.getString("title", null) + // ?: "No Title Set") + // val backgroundIntent = HomeWidgetBackgroundIntent.getBroadcast( + // context, + // Uri.parse("homeWidgetExample://titleClicked") + // ) + // setOnClickPendingIntent(R.id.widget_title, backgroundIntent) + // + // val message = widgetData.getString("message", null) + // setTextViewText(R.id.widget_message, message + // ?: "No Message Set") + // // Show Images saved with `renderFlutterWidget` + // val image = widgetData.getString("dashIcon", null) + // if (image != null) { + // setImageViewBitmap(R.id.widget_img, BitmapFactory.decodeFile(image)) + // setViewVisibility(R.id.widget_img, View.VISIBLE) + // } else { + // setViewVisibility(R.id.widget_img, View.GONE) + // } + // + // // Detect App opened via Click inside Flutter + // val pendingIntentWithData = HomeWidgetLaunchIntent.getActivity( + // context, + // MainActivity::class.java, + // Uri.parse("homeWidgetExample://message?message=$message")) + // setOnClickPendingIntent(R.id.widget_message, pendingIntentWithData) + } + // Get the layout for the widget and attach an onClick listener to + // the button. + // val views: RemoteViews = RemoteViews( + // context.packageName, + // R.layout.appwidget_provider_layout + // ).apply { + // setOnClickPendingIntent(R.id.button, pendingIntent) + // } + + // Tell the AppWidgetManager to perform an update on the current + // widget. + appWidgetManager.updateAppWidget(appWidgetId, views) + } + } +} diff --git a/android/app/src/main/res/layout/analogue_clock_widget.xml b/android/app/src/main/res/layout/analogue_clock_widget.xml new file mode 100644 index 00000000..8f85f743 --- /dev/null +++ b/android/app/src/main/res/layout/analogue_clock_widget.xml @@ -0,0 +1,32 @@ + + + + + + diff --git a/android/app/src/main/res/layout/digital_clock_date_widget.xml b/android/app/src/main/res/layout/digital_clock_date_widget.xml new file mode 100644 index 00000000..e0194f67 --- /dev/null +++ b/android/app/src/main/res/layout/digital_clock_date_widget.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/layout/digital_clock_widget.xml b/android/app/src/main/res/layout/digital_clock_widget.xml new file mode 100644 index 00000000..e587fbd4 --- /dev/null +++ b/android/app/src/main/res/layout/digital_clock_widget.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/xml/analogue_clock_widget.xml b/android/app/src/main/res/xml/analogue_clock_widget.xml new file mode 100644 index 00000000..631b3554 --- /dev/null +++ b/android/app/src/main/res/xml/analogue_clock_widget.xml @@ -0,0 +1,12 @@ + + + diff --git a/android/app/src/main/res/xml/digital_clock_date_widget.xml b/android/app/src/main/res/xml/digital_clock_date_widget.xml new file mode 100644 index 00000000..b5f74582 --- /dev/null +++ b/android/app/src/main/res/xml/digital_clock_date_widget.xml @@ -0,0 +1,12 @@ + + + diff --git a/android/app/src/main/res/xml/digital_clock_widget.xml b/android/app/src/main/res/xml/digital_clock_widget.xml new file mode 100644 index 00000000..4f340999 --- /dev/null +++ b/android/app/src/main/res/xml/digital_clock_widget.xml @@ -0,0 +1,12 @@ + + + diff --git a/android/build.gradle b/android/build.gradle index e0f6c98a..abc3b441 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -3,18 +3,6 @@ allprojects { google() mavenCentral() } - - // subprojects { - // afterEvaluate { project -> - // if (project.hasProperty('android')) { - // project.android { - // if (namespace == null) { - // namespace project.group - // } - // } - // } - // } - // } } rootProject.buildDir = '../build' diff --git a/assets/contributors.json b/assets/contributors.json deleted file mode 100644 index 085bd7e0..00000000 --- a/assets/contributors.json +++ /dev/null @@ -1,65 +0,0 @@ -[ - { - "login": "AhsanSarwar45", - "id": 41967492, - "node_id": "MDQ6VXNlcjQxOTY3NDky", - "avatar_url": "https://avatars.githubusercontent.com/u/41967492?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/AhsanSarwar45", - "html_url": "https://github.com/AhsanSarwar45", - "followers_url": "https://api.github.com/users/AhsanSarwar45/followers", - "following_url": "https://api.github.com/users/AhsanSarwar45/following{/other_user}", - "gists_url": "https://api.github.com/users/AhsanSarwar45/gists{/gist_id}", - "starred_url": "https://api.github.com/users/AhsanSarwar45/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/AhsanSarwar45/subscriptions", - "organizations_url": "https://api.github.com/users/AhsanSarwar45/orgs", - "repos_url": "https://api.github.com/users/AhsanSarwar45/repos", - "events_url": "https://api.github.com/users/AhsanSarwar45/events{/privacy}", - "received_events_url": "https://api.github.com/users/AhsanSarwar45/received_events", - "type": "User", - "site_admin": false, - "contributions": 428 - }, - { - "login": "azeem-io", - "id": 84540569, - "node_id": "MDQ6VXNlcjg0NTQwNTY5", - "avatar_url": "https://avatars.githubusercontent.com/u/84540569?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/azeem-io", - "html_url": "https://github.com/azeem-io", - "followers_url": "https://api.github.com/users/azeem-io/followers", - "following_url": "https://api.github.com/users/azeem-io/following{/other_user}", - "gists_url": "https://api.github.com/users/azeem-io/gists{/gist_id}", - "starred_url": "https://api.github.com/users/azeem-io/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/azeem-io/subscriptions", - "organizations_url": "https://api.github.com/users/azeem-io/orgs", - "repos_url": "https://api.github.com/users/azeem-io/repos", - "events_url": "https://api.github.com/users/azeem-io/events{/privacy}", - "received_events_url": "https://api.github.com/users/azeem-io/received_events", - "type": "User", - "site_admin": false, - "contributions": 11 - }, - { - "login": "inson1", - "id": 75314629, - "node_id": "MDQ6VXNlcjc1MzE0NjI5", - "avatar_url": "https://avatars.githubusercontent.com/u/75314629?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/inson1", - "html_url": "https://github.com/inson1", - "followers_url": "https://api.github.com/users/inson1/followers", - "following_url": "https://api.github.com/users/inson1/following{/other_user}", - "gists_url": "https://api.github.com/users/inson1/gists{/gist_id}", - "starred_url": "https://api.github.com/users/inson1/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/inson1/subscriptions", - "organizations_url": "https://api.github.com/users/inson1/orgs", - "repos_url": "https://api.github.com/users/inson1/repos", - "events_url": "https://api.github.com/users/inson1/events{/privacy}", - "received_events_url": "https://api.github.com/users/inson1/received_events", - "type": "User", - "site_admin": false, - "contributions": 3 - } -] diff --git a/assets/contributors/avatars/41967492?v=4.jpg b/assets/contributors/avatars/41967492?v=4.jpg new file mode 100644 index 00000000..b71cad74 Binary files /dev/null and b/assets/contributors/avatars/41967492?v=4.jpg differ diff --git a/assets/contributors/avatars/75314629?v=4.jpg b/assets/contributors/avatars/75314629?v=4.jpg new file mode 100644 index 00000000..4245dbde Binary files /dev/null and b/assets/contributors/avatars/75314629?v=4.jpg differ diff --git a/assets/contributors/avatars/84540569?v=4.jpg b/assets/contributors/avatars/84540569?v=4.jpg new file mode 100644 index 00000000..bff7da9d Binary files /dev/null and b/assets/contributors/avatars/84540569?v=4.jpg differ diff --git a/assets/contributors/git.json b/assets/contributors/git.json new file mode 100644 index 00000000..49cc8fa2 --- /dev/null +++ b/assets/contributors/git.json @@ -0,0 +1,17 @@ +[ + { + "username": "AhsanSarwar45", + "avatar_url": "assets/contributors/avatars/41967492?v=4.jpg", + "profile_url": "https://github.com/AhsanSarwar45" + }, + { + "username": "azeem-io", + "avatar_url": "assets/contributors/avatars/84540569?v=4.jpg", + "profile_url": "https://github.com/azeem-io" + }, + { + "username": "inson1", + "avatar_url": "assets/contributors/avatars/75314629?v=4.jpg", + "profile_url": "https://github.com/inson1" + } +] diff --git a/assets/patreons/patreons.json b/assets/patreons/patreons.json new file mode 100644 index 00000000..ed42f950 --- /dev/null +++ b/assets/patreons/patreons.json @@ -0,0 +1,12 @@ +[ + { + "name": "Potato", + "lifetime_amount": "3.66", + "email": "patreon@cinna.boo" + }, + { + "name": "Thorsten", + "lifetime_amount": "53.76", + "email": "patreon.com@th23.net" + } +] \ No newline at end of file diff --git a/fonts/Montserrat/Montserrat-VariableFont.ttf b/fonts/Montserrat/Montserrat-VariableFont.ttf deleted file mode 100644 index 656db666..00000000 Binary files a/fonts/Montserrat/Montserrat-VariableFont.ttf and /dev/null differ diff --git a/fonts/Montserrat/OFL.txt b/fonts/Montserrat/OFL.txt deleted file mode 100644 index f435ed8b..00000000 --- a/fonts/Montserrat/OFL.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2011 The Montserrat Project Authors (https://github.com/JulietaUla/Montserrat) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/l10n.yaml b/l10n.yaml new file mode 100644 index 00000000..15338f2d --- /dev/null +++ b/l10n.yaml @@ -0,0 +1,3 @@ +arb-dir: lib/l10n +template-arb-file: app_en.arb +output-localization-file: app_localizations.dart diff --git a/lib/alarm/data/alarm_events_list_filters.dart b/lib/alarm/data/alarm_events_list_filters.dart new file mode 100644 index 00000000..79687dfe --- /dev/null +++ b/lib/alarm/data/alarm_events_list_filters.dart @@ -0,0 +1,36 @@ +import 'package:clock_app/alarm/types/alarm_event.dart'; +import 'package:clock_app/common/types/list_filter.dart'; +import 'package:clock_app/common/types/notification_type.dart'; +import 'package:clock_app/common/utils/date_time.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +final List> alarmEventsListFilters = [ + ListFilterSelect( + (context) => AppLocalizations.of(context)!.stateFilterGroup, [ + ListFilter((context) => AppLocalizations.of(context)!.activeFilter, + (event) => event.isActive), + ListFilter((context) => AppLocalizations.of(context)!.inactiveFilter, + (event) => !event.isActive), + ]), + ListFilterSelect( + (context) => AppLocalizations.of(context)!.scheduleDateFilterGroup, [ + ListFilter((context) => AppLocalizations.of(context)!.todayFilter, + (event) => event.startDate.isToday()), + ListFilter((context) => AppLocalizations.of(context)!.tomorrowFilter, + (event) => event.startDate.isTomorrow()), + ]), + ListFilterSelect( + (context) => AppLocalizations.of(context)!.logTypeFilterGroup, [ + ListFilter((context) => AppLocalizations.of(context)!.alarmTitle, + (event) => event.notificationType == ScheduledNotificationType.alarm), + ListFilter((context) => AppLocalizations.of(context)!.timerTitle, + (event) => event.notificationType == ScheduledNotificationType.timer), + ]), + ListFilterSelect( + (context) => AppLocalizations.of(context)!.createdDateFilterGroup, [ + ListFilter((context) => AppLocalizations.of(context)!.todayFilter, + (event) => event.eventTime.isToday()), + ListFilter((context) => AppLocalizations.of(context)!.tomorrowFilter, + (event) => event.eventTime.isTomorrow()), + ]), +]; diff --git a/lib/alarm/data/alarm_list_filters.dart b/lib/alarm/data/alarm_list_filters.dart index 3a132cee..8392cb44 100644 --- a/lib/alarm/data/alarm_list_filters.dart +++ b/lib/alarm/data/alarm_list_filters.dart @@ -3,50 +3,55 @@ import 'package:clock_app/common/types/list_filter.dart'; import 'package:clock_app/common/types/tag.dart'; import 'package:clock_app/common/utils/date_time.dart'; import 'package:clock_app/common/utils/list_storage.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; final List> alarmListFilters = [ - ListFilterSelect("Date", [ - - ListFilter( - 'Today', - (alarm) { + ListFilterSelect( + (context) => AppLocalizations.of(context)!.dateFilterGroup, + [ + ListFilter( + (context) => AppLocalizations.of(context)!.todayFilter, + (alarm) { + if (alarm.currentScheduleDateTime == null) return false; + return alarm.currentScheduleDateTime!.isToday(); + }, + ), + ListFilter((context) => AppLocalizations.of(context)!.tomorrowFilter, + (alarm) { if (alarm.currentScheduleDateTime == null) return false; - return alarm.currentScheduleDateTime!.isToday(); - }, - ), - ListFilter('Tomorrow', (alarm) { - if (alarm.currentScheduleDateTime == null) return false; - return alarm.currentScheduleDateTime!.isTomorrow(); - }), - ]), - ListFilterSelect("State", [ - + return alarm.currentScheduleDateTime!.isTomorrow(); + }), + ], + ), + ListFilterSelect( + (context) => AppLocalizations.of(context)!.stateFilterGroup, [ ListFilter( - 'Active', + (context) => AppLocalizations.of(context)!.activeFilter, (alarm) => alarm.isEnabled && !alarm.isFinished, ), ListFilter( - 'Snoozed', + (context) => AppLocalizations.of(context)!.snoozedFilter, (alarm) => alarm.isSnoozed, ), ListFilter( - 'Disabled', + (context) => AppLocalizations.of(context)!.disabledFilter, (alarm) => !alarm.isEnabled, ), ListFilter( - 'Completed', + (context) => AppLocalizations.of(context)!.completedFilter, (alarm) => alarm.isFinished, ), ]), - // - DynamicListFilterMultiSelect("Tags", () { + // + DynamicListFilterMultiSelect( + (context) => AppLocalizations.of(context)!.tagsSetting, () { final tags = loadListSync("tags"); return tags.map((tag) { - return ListFilter( - tag.name, - (alarm) => alarm.tags.any((element) => element.id == tag.id), - id: tag.id, - ); - }).toList(); + return ListFilter( + (context) => tag.name, + (alarm) => alarm.tags.any((element) => element.id == tag.id), + id: tag.id, + ); + }).toList(); }), - ]; +]; diff --git a/lib/alarm/data/alarm_settings_schema.dart b/lib/alarm/data/alarm_settings_schema.dart index 740af8bf..d6a23c40 100644 --- a/lib/alarm/data/alarm_settings_schema.dart +++ b/lib/alarm/data/alarm_settings_schema.dart @@ -11,58 +11,84 @@ import 'package:clock_app/alarm/widgets/alarm_task_card.dart'; import 'package:clock_app/alarm/widgets/try_alarm_task_button.dart'; import 'package:clock_app/audio/audio_channels.dart'; import 'package:clock_app/audio/types/ringtone_player.dart'; +import 'package:clock_app/common/data/weekdays.dart'; import 'package:clock_app/common/logic/tags.dart'; import 'package:clock_app/common/types/file_item.dart'; +import 'package:clock_app/common/types/popup_action.dart'; import 'package:clock_app/common/types/tag.dart'; import 'package:clock_app/common/utils/ringtones.dart'; +import 'package:clock_app/settings/screens/ringtones_screen.dart'; +import 'package:clock_app/settings/screens/tags_screen.dart'; import 'package:clock_app/settings/types/setting.dart'; import 'package:clock_app/settings/types/setting_enable_condition.dart'; import 'package:clock_app/settings/types/setting_group.dart'; import 'package:clock_app/timer/types/time_duration.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; const alarmSchemaVersion = 5; SettingGroup alarmSettingsSchema = SettingGroup( version: alarmSchemaVersion, "AlarmSettings", + (context) => AppLocalizations.of(context)!.alarmTitle, [ - StringSetting("Label", ""), + StringSetting( + "Label", (context) => AppLocalizations.of(context)!.labelField, ""), SettingGroup( "Schedule", + (context) => AppLocalizations.of(context)!.alarmScheduleSettingGroup, [ SelectSetting( "Type", + (context) => AppLocalizations.of(context)!.scheduleTypeField, [ - SelectSettingOption("Once", OnceAlarmSchedule, - description: "Will ring at the next occurrence of the time"), - SelectSettingOption("Daily", DailyAlarmSchedule, - description: "Will ring every day"), - SelectSettingOption("On Specified Week Days", WeeklyAlarmSchedule, - description: "Will repeat on the specified week days"), - SelectSettingOption("On Specific Dates", DatesAlarmSchedule, - description: "Will repeat on the specified dates"), - SelectSettingOption("Date Range", RangeAlarmSchedule, - description: "Will repeat during the specified date range"), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.scheduleTypeOnce, + OnceAlarmSchedule, + getDescription: (context) => + AppLocalizations.of(context)!.scheduleTypeOnceDescription, + ), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.scheduleTypeDaily, + DailyAlarmSchedule, + getDescription: (context) => + AppLocalizations.of(context)!.scheduleTypeDailyDescription, + ), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.scheduleTypeWeek, + WeeklyAlarmSchedule, + getDescription: (context) => + AppLocalizations.of(context)!.scheduleTypeWeekDescription, + ), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.scheduleTypeDate, + DatesAlarmSchedule, + getDescription: (context) => + AppLocalizations.of(context)!.scheduleTypeDateDescription, + ), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.scheduleTypeRange, + RangeAlarmSchedule, + getDescription: (context) => + AppLocalizations.of(context)!.scheduleTypeRangeDescription, + ), ], ), ToggleSetting( "Week Days", - [ - ToggleSettingOption("M", 1), - ToggleSettingOption("T", 2), - ToggleSettingOption("W", 3), - ToggleSettingOption("T", 4), - ToggleSettingOption("F", 5), - ToggleSettingOption("S", 6), - ToggleSettingOption("S", 7), - ], + (context) => AppLocalizations.of(context)!.alarmWeekdaysSetting, + weekdays + .map((weekday) => ToggleSettingOption( + (context) => weekday.getAbbreviation(context), weekday.id)) + .toList(), enableConditions: [ ValueCondition(["Type"], (value) => value == WeeklyAlarmSchedule) ], ), DateTimeSetting( "Dates", + (context) => AppLocalizations.of(context)!.alarmDatesSetting, [], enableConditions: [ ValueCondition(["Type"], (value) => value == DatesAlarmSchedule) @@ -70,6 +96,7 @@ SettingGroup alarmSettingsSchema = SettingGroup( ), DateTimeSetting( "Date Range", + (context) => AppLocalizations.of(context)!.alarmRangeSetting, [], rangeOnly: true, enableConditions: [ @@ -78,57 +105,105 @@ SettingGroup alarmSettingsSchema = SettingGroup( ), SelectSetting( "Interval", + (context) => AppLocalizations.of(context)!.alarmIntervalSetting, [ - SelectSettingOption("Daily", RangeInterval.daily), - SelectSettingOption("Weekly", RangeInterval.weekly), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.alarmIntervalDaily, + RangeInterval.daily), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.alarmIntervalWeekly, + RangeInterval.weekly), ], enableConditions: [ ValueCondition(["Type"], (value) => value == RangeAlarmSchedule) ], ), - SwitchSetting("Delete After Ringing", false, enableConditions: [ - ValueCondition(["Type"], (value) => value == OnceAlarmSchedule) - ]), - SwitchSetting("Delete After Finishing", false, enableConditions: [ - ValueCondition( - ["Type"], - (value) => [RangeAlarmSchedule, DatesAlarmSchedule].contains(value), - ) - ]), + SwitchSetting( + "Delete After Ringing", + (context) => + AppLocalizations.of(context)!.alarmDeleteAfterRingingSetting, + false, + enableConditions: [ + ValueCondition(["Type"], (value) => value == OnceAlarmSchedule) + ]), + SwitchSetting( + "Delete After Finishing", + (context) => + AppLocalizations.of(context)!.alarmDeleteAfterFinishingSetting, + false, + enableConditions: [ + ValueCondition( + ["Type"], + (value) => + [RangeAlarmSchedule, DatesAlarmSchedule].contains(value), + ) + ]), ], icon: Icons.timer, ), SettingGroup( "Sound and Vibration", + (context) => AppLocalizations.of(context)!.soundAndVibrationSettingGroup, [ SettingGroup( "Sound", + (context) => AppLocalizations.of(context)!.soundSettingGroup, [ DynamicSelectSetting( "Melody", + (context) => AppLocalizations.of(context)!.melodySetting, getRingtoneOptions, onChange: (context, index) { RingtonePlayer.stop(); }, - + actions: [ + MenuAction( + "Add", + (context) async { + await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => const RingtonesScreen()), + ); + }, + Icons.add, + ), + ], // shouldCloseOnSelect: false, ), SelectSetting( - "Audio Channel", audioChannelOptions, - onChange: (context, index) { - RingtonePlayer.stop(); - }), - SliderSetting("Volume", 0, 100, 100, unit: "%"), - SwitchSetting("Rising Volume", false, - description: "Gradually increase volume over time"), + "Audio Channel", + (context) => AppLocalizations.of(context)!.audioChannelSetting, + audioChannelOptions, + onChange: (context, index) { + RingtonePlayer.stop(); + }, + ), + SliderSetting( + "Volume", + (context) => AppLocalizations.of(context)!.volumeSetting, + 0, + 100, + 100, + unit: "%"), + SwitchSetting( + "Rising Volume", + (context) => AppLocalizations.of(context)!.risingVolumeSetting, + false, + + // description: "Gradually increase volume over time", + ), DurationSetting( - "Time To Full Volume", const TimeDuration(minutes: 1), + "Time To Full Volume", + (context) => + AppLocalizations.of(context)!.timeToFullVolumeSetting, + const TimeDuration(minutes: 1), enableConditions: [ ValueCondition(["Rising Volume"], (value) => value == true) ]), ], ), - SwitchSetting("Vibration", false), + SwitchSetting("Vibration", + (context) => AppLocalizations.of(context)!.vibrationSetting, false), ], icon: Icons.volume_up, summarySettings: [ @@ -138,25 +213,53 @@ SettingGroup alarmSettingsSchema = SettingGroup( ), SettingGroup( "Snooze", + (context) => AppLocalizations.of(context)!.snoozeSettingGroup, [ - SwitchSetting("Enabled", true), - SliderSetting("Length", 1, 30, 5, unit: "minutes", enableConditions: [ - ValueCondition(["Enabled"], (value) => value == true) - ]), - SliderSetting("Max Snoozes", 1, 10, 3, + SwitchSetting( + "Enabled", + (context) => AppLocalizations.of(context)!.snoozeEnableSetting, + true), + SliderSetting( + "Length", + (context) => AppLocalizations.of(context)!.snoozeLengthSetting, + 1, + 30, + 5, + unit: "minutes", + enableConditions: [ + ValueCondition(["Enabled"], (value) => value == true) + ]), + SliderSetting( + "Max Snoozes", + (context) => AppLocalizations.of(context)!.maxSnoozesSetting, + 1, + 10, + 3, unit: "times", snapLength: 1, - description: - "The maximum number of times the alarm can be snoozed before it is dismissed", + // description: + // "The maximum number of times the alarm can be snoozed before it is dismissed", + enableConditions: [ + ValueCondition(["Enabled"], (value) => value == true) + ]), + SettingGroup( + "While Snoozed", + (context) => AppLocalizations.of(context)!.whileSnoozedSettingGroup, + [ + SwitchSetting( + "Prevent Disabling", + (context) => AppLocalizations.of(context)! + .snoozePreventDisablingSetting, + false), + SwitchSetting( + "Prevent Deletion", + (context) => AppLocalizations.of(context)! + .snoozePreventDeletionSetting, + false), + ], enableConditions: [ ValueCondition(["Enabled"], (value) => value == true) ]), - SettingGroup("While Snoozed", [ - SwitchSetting("Prevent Disabling", false), - SwitchSetting("Prevent Deletion", false), - ], enableConditions: [ - ValueCondition(["Enabled"], (value) => value == true) - ]), ], icon: Icons.snooze_rounded, summarySettings: [ @@ -166,6 +269,7 @@ SettingGroup alarmSettingsSchema = SettingGroup( ), ListSetting( "Tasks", + (context) => AppLocalizations.of(context)!.tasksSetting, [], alarmTaskSchemasMap.keys.map((key) => AlarmTask(key)).toList(), addCardBuilder: (item) => AlarmTaskCard(task: item, isAddCard: true), @@ -185,8 +289,20 @@ SettingGroup alarmSettingsSchema = SettingGroup( ), DynamicMultiSelectSetting( "Tags", + (context) => AppLocalizations.of(context)!.tagsSetting, getTagOptions, defaultValue: [], + actions: [ + MenuAction( + "Add", + (context) async { + await Navigator.of(context).push( + MaterialPageRoute(builder: (context) => const TagsScreen()), + ); + }, + Icons.add, + ), + ], ), // ListSetting() diff --git a/lib/alarm/data/alarm_sort_options.dart b/lib/alarm/data/alarm_sort_options.dart index 3c9387e0..90d972cc 100644 --- a/lib/alarm/data/alarm_sort_options.dart +++ b/lib/alarm/data/alarm_sort_options.dart @@ -1,17 +1,17 @@ import 'package:clock_app/alarm/types/alarm.dart'; import 'package:clock_app/common/types/list_filter.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -const List> alarmSortOptions = [ - ListSortOption( - "Remaining Time Descending", "9-1", sortRemainingTimeDescending), - ListSortOption("Remaining Time Ascending", "1-9", sortRemainingTimeAscending), - ListSortOption("Date Descending", "30-1", sortDateDescending), - ListSortOption("Date Ascending", "1-30", sortDateAscending), - ListSortOption("Name Ascending", "A-Z", sortNameAscending), - ListSortOption("Name Descending", "Z-A", sortNameDescending), - ListSortOption("Time of Day Ascending", "0:00-12:00", sortTimeOfDayAscending), - ListSortOption( - "Time of Day Descending", "12:00-0:00", sortTimeOfDayDescending), + +final List> alarmSortOptions = [ + ListSortOption((context) => AppLocalizations.of(context)!.remainingTimeDesc, sortRemainingTimeDescending), + ListSortOption((context) => AppLocalizations.of(context)!.remainingTimeAsc, sortRemainingTimeAscending), + // ListSortOption("Date Descending", "30-1", sortDateDescending), + // ListSortOption("Date Ascending", "1-30", sortDateAscending), + ListSortOption((context) => AppLocalizations.of(context)!.nameAsc, sortNameAscending), + ListSortOption((context) => AppLocalizations.of(context)!.nameDesc, sortNameDescending), + ListSortOption((context) => AppLocalizations.of(context)!.timeOfDayAsc, sortTimeOfDayAscending), + ListSortOption((context) => AppLocalizations.of(context)!.timeOfDayDesc, sortTimeOfDayDescending), ]; int sortRemainingTimeDescending(Alarm a, Alarm b) { diff --git a/lib/alarm/data/alarm_task_schemas.dart b/lib/alarm/data/alarm_task_schemas.dart index bb32d11a..78361a32 100644 --- a/lib/alarm/data/alarm_task_schemas.dart +++ b/lib/alarm/data/alarm_task_schemas.dart @@ -4,25 +4,38 @@ import 'package:clock_app/alarm/widgets/tasks/retype_task.dart'; import 'package:clock_app/alarm/widgets/tasks/sequence_task.dart'; import 'package:clock_app/settings/types/setting.dart'; import 'package:clock_app/settings/types/setting_group.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; Map alarmTaskSchemasMap = { AlarmTaskType.math: AlarmTaskSchema( - "Math Problems", - SettingGroup("Math Problems Settings", [ + (context) => AppLocalizations.of(context)!.mathTask, + SettingGroup("Math Problems Settings", + (context) => AppLocalizations.of(context)!.mathTask, [ SelectSetting( "Difficulty", + (context) => AppLocalizations.of(context)!.mathTaskDifficultySetting, [ SelectSettingOption( - "Easy (X + Y)", MathTaskDifficultyLevel([Operator.add])), + (context) => AppLocalizations.of(context)!.mathEasyDifficulty, + MathTaskDifficultyLevel([Operator.add])), SelectSettingOption( - "Medium (X × Y)", MathTaskDifficultyLevel([Operator.multiply])), - SelectSettingOption("Hard (X × Y + Z)", + (context) => AppLocalizations.of(context)!.mathMediumDifficulty, + MathTaskDifficultyLevel([Operator.multiply])), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.mathHardDifficulty, MathTaskDifficultyLevel([Operator.multiply, Operator.add])), - SelectSettingOption("Very Hard (X × Y × Z)", + SelectSettingOption( + (context) => AppLocalizations.of(context)!.mathVeryHardDifficulty, MathTaskDifficultyLevel([Operator.multiply, Operator.multiply])), ], ), - SliderSetting("Number of problems", 1, 10, 1, snapLength: 1), + SliderSetting( + "Number of problems", + (context) => AppLocalizations.of(context)!.numberOfProblemsSetting, + 1, + 10, + 1, + snapLength: 1), ]), (onSolve, settings) { return MathTask( @@ -32,23 +45,54 @@ Map alarmTaskSchemasMap = { }, ), AlarmTaskType.retype: AlarmTaskSchema( - "Retype Text", - SettingGroup("Retype Text Settings", [ - SliderSetting("Number of characters", 5, 20, 5, snapLength: 1), - SwitchSetting("Include numbers", false), - SwitchSetting("Include lowercase", false), - SliderSetting("Number of problems", 1, 10, 1, snapLength: 1), - + (context) => AppLocalizations.of(context)!.retypeTask, + SettingGroup("Retype Text Settings", + (context) => AppLocalizations.of(context)!.retypeTask, [ + SliderSetting( + "Number of characters", + (context) => AppLocalizations.of(context)!.retypeNumberChars, + 5, + 20, + 5, + snapLength: 1), + SwitchSetting( + "Include numbers", + (context) => AppLocalizations.of(context)!.retypeIncludeNumSetting, + false), + SwitchSetting( + "Include lowercase", + (context) => AppLocalizations.of(context)!.retypeLowercaseSetting, + true), + SliderSetting( + "Number of problems", + (context) => AppLocalizations.of(context)!.numberOfProblemsSetting, + 1, + 10, + 1, + snapLength: 1), ]), (onSolve, settings) { return RetypeTask(onSolve: onSolve, settings: settings); }, ), AlarmTaskType.sequence: AlarmTaskSchema( - "Sequence", - SettingGroup("Sequence Settings", [ - SliderSetting("Sequence length", 3, 10, 3, snapLength: 1), - SliderSetting("Grid size", 2, 5, 3, snapLength: 1), + (context) => AppLocalizations.of(context)!.sequenceTask, + SettingGroup("Sequence Settings", + (context) => AppLocalizations.of(context)!.sequenceTask, [ + SliderSetting( + "Sequence length", + (context) => AppLocalizations.of(context)!.sequenceLengthSetting, + 3, + 10, + 3, + snapLength: 1), + SliderSetting( + "Grid size", + (context) => AppLocalizations.of(context)!.sequenceGridSizeSetting, + 2, + 5, + 3, + snapLength: 1), ]), (onSolve, settings) { return SequenceTask(onSolve: onSolve, settings: settings); diff --git a/lib/alarm/logic/alarm_isolate.dart b/lib/alarm/logic/alarm_isolate.dart index 272a0b71..332cd03c 100644 --- a/lib/alarm/logic/alarm_isolate.dart +++ b/lib/alarm/logic/alarm_isolate.dart @@ -8,7 +8,6 @@ import 'package:clock_app/system/logic/initialize_isolate.dart'; import 'package:clock_app/timer/types/time_duration.dart'; import 'package:clock_app/timer/types/timer.dart'; import 'package:flutter/foundation.dart'; -import 'package:get_storage/get_storage.dart'; import 'package:clock_app/alarm/logic/schedule_alarm.dart'; import 'package:clock_app/alarm/logic/update_alarms.dart'; import 'package:clock_app/alarm/types/alarm.dart'; @@ -19,6 +18,8 @@ import 'package:clock_app/alarm/utils/alarm_id.dart'; import 'package:clock_app/common/utils/time_of_day.dart'; import 'package:clock_app/timer/logic/update_timers.dart'; import 'package:clock_app/timer/utils/timer_id.dart'; +import 'package:flutter/services.dart'; +import 'package:receive_intent/receive_intent.dart'; const String stopAlarmPortName = "stopAlarmPort"; const String updatePortName = "updatePort"; @@ -51,6 +52,16 @@ void triggerScheduledNotification(int scheduleId, Json params) async { stopScheduledNotification(message); }); + try { + final receivedIntent = await ReceiveIntent.getInitialIntent(); + print("reeeeeeeeeeeeeeeeeeeeeeeeeee ${receivedIntent}"); + // Validate receivedIntent and warn the user, if it is not correct, + // but keep in mind it could be `null` or "empty"(`receivedIntent.isNull`). + } on PlatformException { + // Handle exception + } + + if (notificationType == ScheduledNotificationType.alarm) { triggerAlarm(scheduleId, params); } else if (notificationType == ScheduledNotificationType.timer) { @@ -104,8 +115,6 @@ void triggerAlarm(int scheduleId, Json params) async { return; } - GetStorage().write("fullScreenNotificationRecentlyShown", true); - // Pause any currently ringing timers. We will continue them after the alarm // is dismissed if (RingingManager.isTimerRinging) { @@ -168,9 +177,6 @@ void triggerTimer(int scheduleId, Json params) async { await updateTimers("triggerTimer(): Updating all timers on trigger"); - // Notify the front-end to update the timers - GetStorage().write("fullScreenNotificationRecentlyShown", true); - // Pause any currently ringing alarms. We will continue them after the timer // is dismissed if (RingingManager.isAlarmRinging) { diff --git a/lib/alarm/logic/schedule_description.dart b/lib/alarm/logic/schedule_description.dart index 811bd92d..8e3f95db 100644 --- a/lib/alarm/logic/schedule_description.dart +++ b/lib/alarm/logic/schedule_description.dart @@ -13,45 +13,52 @@ import 'package:clock_app/common/utils/time_format.dart'; import 'package:clock_app/common/utils/weekday_utils.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; String getAlarmScheduleDescription(BuildContext context, Alarm alarm, String dateFormat, TimeFormat timeFormat) { String suffix = ''; if (alarm.shouldSkipNextAlarm) { - suffix = ' (skipping next occurence)'; + suffix = ' ${AppLocalizations.of(context)!.skippingDescriptionSuffix}'; } if (alarm.isSnoozed) { - return 'Snoozed until ${DateFormat(getTimeFormatString(context, timeFormat)).format(alarm.snoozeTime!)}'; + return AppLocalizations.of(context)!.alarmDescriptionSnooze( + DateFormat(getTimeFormatString(context, timeFormat)) + .format(alarm.snoozeTime!)); } if (alarm.isFinished) { - return 'No future dates'; + return AppLocalizations.of(context)!.alarmDescriptionFinished; } if (!alarm.isEnabled) { - return 'Not scheduled'; + return AppLocalizations.of(context)!.alarmDescriptionNotScheduled; } switch (alarm.scheduleType) { case OnceAlarmSchedule: - return 'Just ${alarm.time.toHours() > DateTime.now().toHours() ? 'today' : 'tomorrow'}$suffix'; + return '${alarm.time.toHours() > DateTime.now().toHours() ? AppLocalizations.of(context)!.alarmDescriptionToday : AppLocalizations.of(context)!.alarmDescriptionTomorrow}$suffix'; case DailyAlarmSchedule: - return 'Every day$suffix'; + return '${AppLocalizations.of(context)!.alarmDescriptionEveryDay}$suffix'; case WeeklyAlarmSchedule: List alarmWeekdays = alarm.weekdays; if (alarmWeekdays.length == 7) { - return 'Every day$suffix'; + return '${AppLocalizations.of(context)!.alarmDescriptionEveryDay}$suffix'; } if (alarmWeekdays.length == 2 && - weekdaysContainsAll(alarmWeekdays, ['Sat', 'Sun'])) { - return 'Every weekend$suffix'; + weekdaysContainsAll(alarmWeekdays, [6, 7])) { + return '${AppLocalizations.of(context)!.alarmDescriptionWeekend}$suffix'; } if (alarmWeekdays.length == 5 && - weekdaysContainsAll( - alarmWeekdays, ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'])) { - return 'Every weekday$suffix'; + weekdaysContainsAll(alarmWeekdays, [1, 2, 3, 4, 5])) { + return '${AppLocalizations.of(context)!.alarmDescriptionWeekday}$suffix'; } - return 'Every ${weekdays.where((weekday) => alarmWeekdays.contains(weekday)).map((weekday) => weekday.displayName).join(', ')}$suffix'; + final weekdaysString = weekdays + .where((weekday) => alarmWeekdays.contains(weekday)) + .map((weekday) => weekday.getDisplayName(context)) + .join(', '); + return '${AppLocalizations.of(context)!.alarmDescriptionWeekly(weekdaysString)}$suffix'; case DatesAlarmSchedule: List dates = alarm.dates; - return 'On ${DateFormat(dateFormat).format(dates[0])}${dates.length > 1 ? ' and ${dates.length - 1} other date${dates.length > 2 ? 's' : ''} ' : ''}$suffix'; + return '${AppLocalizations.of(context)!.alarmDescriptionDates(dates.length - 1, DateFormat(dateFormat).format(dates[0]))}$suffix'; + /* return 'On ${DateFormat(dateFormat).format(dates[0])}${dates.length > 1 ? ' and ${dates.length - 1} other date${dates.length > 2 ? 's' : ''} ' : ''}$suffix'; */ case RangeAlarmSchedule: DateTime rangeStart = alarm.startDate; DateTime rangeEnd = alarm.endDate; @@ -72,9 +79,9 @@ String getAlarmScheduleDescription(BuildContext context, Alarm alarm, endString = DateFormat('d MMM').format(rangeEnd); } } - - return '${interval == RangeInterval.daily ? "Daily" : "Weekly"} from $startString to $endString$suffix'; + return '${AppLocalizations.of(context)!.alarmDescriptionRange(endString, interval == RangeInterval.daily ? "daily" : "weekly", startString)}$suffix'; + // return '${interval == RangeInterval.daily ? "Daily" : "Weekly"} from $startString to $endString$suffix'; default: - return 'Not scheduled'; + return AppLocalizations.of(context)!.alarmDescriptionNotScheduled; } } diff --git a/lib/alarm/screens/alarm_events_screen.dart b/lib/alarm/screens/alarm_events_screen.dart index c0f39141..3222f224 100644 --- a/lib/alarm/screens/alarm_events_screen.dart +++ b/lib/alarm/screens/alarm_events_screen.dart @@ -2,11 +2,9 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; +import 'package:clock_app/alarm/data/alarm_events_list_filters.dart'; import 'package:clock_app/alarm/types/alarm_event.dart'; import 'package:clock_app/alarm/widgets/alarm_event_card.dart'; -import 'package:clock_app/common/types/list_filter.dart'; -import 'package:clock_app/common/types/notification_type.dart'; -import 'package:clock_app/common/utils/date_time.dart'; import 'package:clock_app/common/utils/json_serialize.dart'; import 'package:clock_app/common/utils/list_storage.dart'; import 'package:clock_app/common/widgets/fab.dart'; @@ -25,27 +23,8 @@ class AlarmEventsScreen extends StatefulWidget { State createState() => _AlarmEventsScreenState(); } -final List> alarmEventsListFilters = [ - ListFilterSelect("State", [ - ListFilter('Active', (event) => event.isActive), - ListFilter('Inactive', (event) => !event.isActive), - ]), - ListFilterSelect("Schedule Date", [ - ListFilter('Today', (event) => event.startDate.isToday()), - ListFilter('Tomorrow', (event) => event.startDate.isTomorrow()), - ]), - ListFilterSelect("Type", [ - ListFilter('Alarm', (event) => event.notificationType == ScheduledNotificationType.alarm), - ListFilter('Timer', (event) => event.notificationType == ScheduledNotificationType.timer), - ]), - ListFilterSelect("Created Date", [ - ListFilter('Today', (event) => event.eventTime.isToday()), - ListFilter('Tomorrow', (event) => event.eventTime.isTomorrow()), - ]), -]; - class _AlarmEventsScreenState extends State { final _listController = PersistentListController(); List searchedItems = []; diff --git a/lib/alarm/screens/alarm_screen.dart b/lib/alarm/screens/alarm_screen.dart index 28fd8fce..cc96b771 100644 --- a/lib/alarm/screens/alarm_screen.dart +++ b/lib/alarm/screens/alarm_screen.dart @@ -18,6 +18,8 @@ import 'package:clock_app/settings/data/settings_schema.dart'; import 'package:clock_app/settings/types/setting.dart'; import 'package:flutter/material.dart'; import 'package:great_list_view/great_list_view.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + typedef AlarmCardBuilder = Widget Function( @@ -124,7 +126,7 @@ class _AlarmScreenState extends State { Future _handleEnableChangeAlarm(Alarm alarm, bool value) async { if (!alarm.canBeDisabledWhenSnoozed && !value && alarm.isSnoozed) { - showSnackBar(context, "Cannot disable alarm while it is snoozed", + showSnackBar(context, AppLocalizations.of(context)!.cannotDisableAlarmWhileSnoozedSnackbar, fab: true, navBar: true); } else { await alarm.setIsEnabled(value, @@ -138,7 +140,7 @@ class _AlarmScreenState extends State { List alarms, bool value) async { for (var alarm in alarms) { if (!alarm.canBeDisabledWhenSnoozed && !value && alarm.isSnoozed) { - showSnackBar(context, "Cannot disable alarm while it is snoozed", + showSnackBar(context, AppLocalizations.of(context)!.cannotDisableAlarmWhileSnoozedSnackbar, fab: true, navBar: true); } else { await alarm.setIsEnabled(value, @@ -178,10 +180,9 @@ class _AlarmScreenState extends State { await showTimePickerDialog( context: context, initialTime: TimeOfDay.now(), - title: "Select Time", - cancelText: "Cancel", -// initialEntryMode: TimePickerEntryMode.dial, - confirmText: "Save", + title: AppLocalizations.of(context)!.selectTime, + cancelText: AppLocalizations.of(context)!.cancelButton, + confirmText: AppLocalizations.of(context)!.saveButton, useSimple: false, ); @@ -218,31 +219,31 @@ class _AlarmScreenState extends State { onDeleteItem: (alarm) async { await alarm.disable(); }, - placeholderText: "No alarms created", + placeholderText: AppLocalizations.of(context)!.noAlarmMessage, reloadOnPop: true, listFilters: _showFilters.value ? alarmListFilters : [], customActions: _showFilters.value ? [ ListFilterCustomAction( - name: "Enable all filtered alarms", + name: AppLocalizations.of(context)!.enableAllFilteredAlarmsAction, icon: Icons.alarm_on_rounded, action: (alarms) { _handleEnableChangeMultiple(alarms, true); }), ListFilterCustomAction( - name: "Disable all filtered alarms", + name: AppLocalizations.of(context)!.disableAllFilteredAlarmsAction, icon: Icons.alarm_off_rounded, action: (alarms) { _handleEnableChangeMultiple(alarms, false); }), ListFilterCustomAction( - name: "Skip all filtered alarms", + name: AppLocalizations.of(context)!.skipAllFilteredAlarmsAction, icon: Icons.skip_next_rounded, action: (alarms) { _handleSkipChangeMultiple(alarms, true); }), ListFilterCustomAction( - name: "Cancel skip all filtered alarms", + name: AppLocalizations.of(context)!.cancelSkipAllFilteredAlarmsAction, icon: Icons.skip_next_rounded, action: (alarms) { _handleSkipChangeMultiple(alarms, false); diff --git a/lib/alarm/types/alarm.dart b/lib/alarm/types/alarm.dart index e008b4d0..90d6c2ef 100644 --- a/lib/alarm/types/alarm.dart +++ b/lib/alarm/types/alarm.dart @@ -46,6 +46,7 @@ class Alarm extends CustomizableListItem { DateTime? _skippedTime; SettingGroup _settings = SettingGroup( "Alarm Settings", + (context) => "Alarm Settings", appSettings .getGroup("Alarm") .getGroup("Default Settings") @@ -388,6 +389,7 @@ class Alarm extends CustomizableListItem { _snoozeCount = json['snoozeCount'] ?? 0; _settings = SettingGroup( "Alarm Settings", + (context) => "Alarm Settings", appSettings .getGroup("Alarm") .getGroup("Default Settings") diff --git a/lib/alarm/types/alarm_task.dart b/lib/alarm/types/alarm_task.dart index c6db1bc9..a1c83c02 100644 --- a/lib/alarm/types/alarm_task.dart +++ b/lib/alarm/types/alarm_task.dart @@ -16,14 +16,14 @@ typedef AlarmTaskBuilder = Widget Function( Function() onSolve, SettingGroup settings); class AlarmTaskSchema extends JsonSerializable { - final String name; + final String Function(BuildContext) getLocalizedName; final SettingGroup settings; final AlarmTaskBuilder _builder; - const AlarmTaskSchema(this.name, this.settings, this._builder); + const AlarmTaskSchema(this.getLocalizedName, this.settings, this._builder); AlarmTaskSchema.from(AlarmTaskSchema schema) - : name = schema.name, + : getLocalizedName = schema.getLocalizedName, settings = schema.settings.copy(), _builder = schema._builder; @@ -91,7 +91,7 @@ class AlarmTask extends CustomizableListItem { @override bool get isDeletable => true; AlarmTaskSchema get schema => _schema; - String get name => _schema.name; + String Function(BuildContext) get getLocalizedName => _schema.getLocalizedName; @override SettingGroup get settings => _schema.settings; Widget Function(Function() onSolve) get builder => _schema.getBuilder; diff --git a/lib/alarm/widgets/alarm_card.dart b/lib/alarm/widgets/alarm_card.dart index 6e637a94..928a6f94 100644 --- a/lib/alarm/widgets/alarm_card.dart +++ b/lib/alarm/widgets/alarm_card.dart @@ -11,6 +11,7 @@ import 'package:clock_app/common/widgets/clock/clock_display.dart'; import 'package:clock_app/settings/data/settings_schema.dart'; import 'package:clock_app/settings/types/setting.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class AlarmCard extends StatefulWidget { const AlarmCard({ @@ -109,7 +110,7 @@ class _AlarmCardState extends State { ); } return TextButton( - child: Text("Dismiss", + child: Text(AppLocalizations.of(context)!.dismissAlarmButton, maxLines: 1, style: textTheme.labelLarge?.copyWith(color: colorScheme.primary)), onPressed: () async { @@ -204,13 +205,13 @@ class _AlarmCardState extends State { CardEditMenu(actions: [ if (widget.alarm.isDeletable) getDeletePopupAction(context, widget.onPressDelete), - getDuplicatePopupAction(widget.onPressDuplicate), + getDuplicatePopupAction(context, widget.onPressDuplicate), if (widget.alarm.canBeSkipped) - PopupAction( + MenuAction( widget.alarm.shouldSkipNextAlarm - ? "Cancel Skip" - : "Skip Next Alarm", - () { + ? AppLocalizations.of(context)!.cancelSkipAlarmButton + : AppLocalizations.of(context)!.skipAlarmButton, + (context) { if (widget.alarm.shouldSkipNextAlarm) { widget.onSkipChange(false); } else { diff --git a/lib/alarm/widgets/alarm_event_card.dart b/lib/alarm/widgets/alarm_event_card.dart index 0134d4be..64b6076d 100644 --- a/lib/alarm/widgets/alarm_event_card.dart +++ b/lib/alarm/widgets/alarm_event_card.dart @@ -1,7 +1,5 @@ - import 'package:clock_app/alarm/types/alarm_event.dart'; import 'package:clock_app/common/types/notification_type.dart'; -import 'package:clock_app/common/widgets/clock/clock_display.dart'; import 'package:flutter/material.dart'; class AlarmEventCard extends StatelessWidget { @@ -18,25 +16,34 @@ class AlarmEventCard extends StatelessWidget { Color textColor = colorScheme.onSurface.withOpacity(0.8); return Column( - children: [ + children: [ Padding( padding: const EdgeInsets.only( - left: 16.0, - right: 16.0, - top: 8.0 , - bottom: 8.0), + left: 16.0, right: 16.0, top: 8.0, bottom: 8.0), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, children: [ - Text(event.isActive ? "Active" : "Inactive", style: textTheme.labelMedium?.copyWith(color: event.isActive ? colorScheme.primary : colorScheme.onSurface)), - Text('Scheduled for: ${event.startDate}', style: textTheme.labelMedium?.copyWith(color: textColor)), - Text('Type: ${event.notificationType == ScheduledNotificationType.alarm ? "Alarm" : "Timer"}', style: textTheme.labelMedium?.copyWith(color:textColor)), - Text('Created at: ${event.eventTime}', style: textTheme.labelMedium?.copyWith(color: textColor)), - Text('Description: ${event.description}', style: textTheme.labelMedium?.copyWith(color: textColor),maxLines: 5,), - Text('Schedule Id: ${event.scheduleId}', style: textTheme.labelMedium?.copyWith(color: textColor)), - - ], + Text(event.isActive ? "Active" : "Inactive", + style: textTheme.labelMedium?.copyWith( + color: event.isActive + ? colorScheme.primary + : colorScheme.onSurface)), + Text('Scheduled for: ${event.startDate}', + style: textTheme.labelMedium?.copyWith(color: textColor)), + Text( + 'Type: ${event.notificationType == ScheduledNotificationType.alarm ? "Alarm" : "Timer"}', + style: textTheme.labelMedium?.copyWith(color: textColor)), + Text('Created at: ${event.eventTime}', + style: textTheme.labelMedium?.copyWith(color: textColor)), + Text( + 'Description: ${event.description}', + style: textTheme.labelMedium?.copyWith(color: textColor), + maxLines: 5, + ), + Text('Schedule Id: ${event.scheduleId}', + style: textTheme.labelMedium?.copyWith(color: textColor)), + ], ), ), ], diff --git a/lib/alarm/widgets/alarm_task_card.dart b/lib/alarm/widgets/alarm_task_card.dart index 4fed60e7..8db45cfc 100644 --- a/lib/alarm/widgets/alarm_task_card.dart +++ b/lib/alarm/widgets/alarm_task_card.dart @@ -38,7 +38,7 @@ class AlarmTaskCard extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(task.name, style: textTheme.displaySmall), + Text(task.getLocalizedName(context), style: textTheme.displaySmall), ], ), ), @@ -48,7 +48,7 @@ class AlarmTaskCard extends StatelessWidget { if (onPressDelete != null) getDeletePopupAction(context, onPressDelete!), if (onPressDuplicate != null) - getDuplicatePopupAction(onPressDuplicate!), + getDuplicatePopupAction(context, onPressDuplicate!), ]), if (!isAddCard) Icon(FluxIcons.settings, color: colorScheme.onSurface), diff --git a/lib/app.dart b/lib/app.dart index a250256c..8d88e18d 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,6 +1,9 @@ import 'package:awesome_notifications/awesome_notifications.dart'; import 'package:clock_app/alarm/screens/alarm_notification_screen.dart'; +import 'package:clock_app/clock/types/time.dart'; import 'package:clock_app/common/data/app_info.dart'; +import 'package:clock_app/common/utils/time_format.dart'; +import 'package:clock_app/l10n/language_local.dart'; import 'package:clock_app/navigation/data/route_observer.dart'; import 'package:clock_app/navigation/screens/nav_scaffold.dart'; import 'package:clock_app/navigation/types/routes.dart'; @@ -18,10 +21,13 @@ import 'package:clock_app/theme/theme.dart'; import 'package:clock_app/theme/types/style_theme.dart'; import 'package:clock_app/theme/utils/color_scheme.dart'; import 'package:clock_app/timer/screens/timer_notification_screen.dart'; +import 'package:clock_app/widgets/logic/update_widgets.dart'; import 'package:dynamic_color/dynamic_color.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:get_storage/get_storage.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:home_widget/home_widget.dart'; class App extends StatefulWidget { const App({super.key}); @@ -51,27 +57,33 @@ class _AppState extends State { late SettingGroup _colorSettings; late SettingGroup _styleSettings; late Setting _animationSpeedSetting; + late SettingGroup _generalSettings; @override void initState() { super.initState(); + // HomeWidget.updateWidget( + // androidName: 'DigitalClockWidgetProvider', + // ); + setDigitalClockWidgetData(context); + NotificationController.setListeners(); _appearanceSettings = appSettings.getGroup("Appearance"); _colorSettings = _appearanceSettings.getGroup("Colors"); _styleSettings = _appearanceSettings.getGroup("Style"); - _animationSpeedSetting = appSettings - .getGroup("General") - .getGroup("Animations") - .getSetting("Animation Speed"); + _generalSettings = appSettings.getGroup("General"); + _animationSpeedSetting = + _generalSettings.getGroup("Animations").getSetting("Animation Speed"); _animationSpeedSetting.addListener(setAnimationSpeed); + setAnimationSpeed(_animationSpeedSetting.value); } void setAnimationSpeed(dynamic speed) { // setState(() { - timeDilation = 1 / speed; + timeDilation = 1 / speed; // }); } @@ -157,6 +169,13 @@ class _AppState extends State { final AppTheme appTheme = getAppTheme(lightDynamic, darkDynamic); ThemeBrightness themeBrightness = _colorSettings.getSetting("Brightness").value; + Locale locale = _generalSettings.getSetting("Language").value; + // if(!AppLocalizations.supportedLocales.contains(locale)){ + // + // } + // + // print("locaaaaaaaale $locale"); + // print(getLocaleOptions().map((e) => e.value).toList()); return MaterialApp( scaffoldMessengerKey: _messangerKey, @@ -172,6 +191,9 @@ class _AppState extends State { : ThemeMode.dark, initialRoute: Routes.rootRoute, navigatorObservers: [routeObserver], + locale: locale, + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, onGenerateRoute: (settings) { Routes.push(settings.name ?? Routes.rootRoute); switch (settings.name) { diff --git a/lib/audio/audio_channels.dart b/lib/audio/audio_channels.dart index a41e7884..1d102b30 100644 --- a/lib/audio/audio_channels.dart +++ b/lib/audio/audio_channels.dart @@ -1,9 +1,18 @@ import 'package:audio_session/audio_session.dart'; import 'package:clock_app/settings/types/setting.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; List> audioChannelOptions = [ - SelectSettingOption("Alarm", AndroidAudioUsage.alarm), - SelectSettingOption("Media", AndroidAudioUsage.media), - SelectSettingOption("Notification", AndroidAudioUsage.notification), - SelectSettingOption("Ringtone", AndroidAudioUsage.notificationRingtone), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.audioChannelAlarm, + AndroidAudioUsage.alarm), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.audioChannelMedia, + AndroidAudioUsage.media), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.audioChannelNotification, + AndroidAudioUsage.notification), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.audioChannelRingtone, + AndroidAudioUsage.notificationRingtone), ]; diff --git a/lib/audio/logic/audio_session.dart b/lib/audio/logic/audio_session.dart index bd7a9912..35abc10c 100644 --- a/lib/audio/logic/audio_session.dart +++ b/lib/audio/logic/audio_session.dart @@ -7,6 +7,7 @@ Future initializeAudioSession( androidAudioAttributes: AndroidAudioAttributes( usage: usage, contentType: AndroidAudioContentType.music, + ), )); } diff --git a/lib/audio/types/audio.dart b/lib/audio/types/audio.dart deleted file mode 100644 index 2d950589..00000000 --- a/lib/audio/types/audio.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'dart:convert'; - -import 'package:clock_app/common/types/json.dart'; - -// class Audio { -// final String id; -// final String title; -// final String uri; - -// const Audio({ -// required this.id, -// required this.title, -// required this.uri, -// }); - -// factory Audio.fromJson(Json json) => Audio( -// id: json != null ? json['id'] ?? '' : '', -// title: json != null ? json['title'] ?? 'Unknown' : 'Unknown', -// uri: json != null ? json['uri'] ?? '' : '', -// ); - -// Json toJson() => { -// 'id': id, -// 'title': title, -// 'uri': uri, -// }; - -// factory Audio.fromEncodedJson(String encodedJson) => -// Audio.fromJson(json.decode(encodedJson)); -// String toEncodedJson() => json.encode(toJson()); -// @override -// String toString() { -// return 'Ringtone{id: $id, title: $title, uri: $uri}'; -// } - -// Audio copyWith({ -// String? id, -// String? title, -// String? uri, -// }) { -// return Audio( -// id: id ?? this.id, -// title: title ?? this.title, -// uri: uri ?? this.uri, -// ); -// } -// } diff --git a/lib/audio/types/ringtone_manager.dart b/lib/audio/types/ringtone_manager.dart index af7edbd4..03fb34f6 100644 --- a/lib/audio/types/ringtone_manager.dart +++ b/lib/audio/types/ringtone_manager.dart @@ -1,18 +1,8 @@ -import 'package:clock_app/audio/types/audio.dart'; -import 'package:clock_app/common/types/file_item.dart'; -import 'package:clock_app/common/utils/list_storage.dart'; -import 'package:clock_app/settings/data/settings_schema.dart'; -import 'package:flutter_system_ringtones/flutter_system_ringtones.dart'; - class RingtoneManager { - // static List _ringtones = []; - // static List _customRingtones = []; - static String _lastPlayedRingtoneUri = ""; + static String _lastPlayedRingtoneUri = ""; static final List _listeners = []; - // static List get ringtones => _ringtones; - // static List get customRingtones => _customRingtones; static List get listeners => _listeners; static String get lastPlayedRingtoneUri => _lastPlayedRingtoneUri; static set lastPlayedRingtoneUri(String uri) { @@ -29,17 +19,4 @@ class RingtoneManager { static void removeListener(void Function() listener) { _listeners.remove(listener); } - - // static Future updateCustomRingtones() async { - // _customRingtones = await loadList('ringtones'); - // } - - // static Future initialize() async { - // if (_ringtones.isEmpty) { - // _ringtones = await getSystemRingtones(); - // } - // if (_customRingtones.isEmpty) { - // _customRingtones = await loadList('ringtones'); - // } - // } } diff --git a/lib/audio/types/ringtone_player.dart b/lib/audio/types/ringtone_player.dart index bfb3db6c..fd8430e3 100644 --- a/lib/audio/types/ringtone_player.dart +++ b/lib/audio/types/ringtone_player.dart @@ -1,15 +1,9 @@ -import 'dart:io'; -import 'dart:math'; - import 'package:audio_session/audio_session.dart'; import 'package:clock_app/alarm/types/alarm.dart'; import 'package:clock_app/audio/logic/audio_session.dart'; import 'package:clock_app/audio/types/ringtone_manager.dart'; -import 'package:clock_app/common/types/file_item.dart'; -import 'package:clock_app/common/utils/list_storage.dart'; import 'package:clock_app/timer/types/timer.dart'; import 'package:just_audio/just_audio.dart'; -import 'package:pick_or_save/pick_or_save.dart'; import 'package:vibration/vibration.dart'; class RingtonePlayer { diff --git a/lib/clock/screens/search_city_screen.dart b/lib/clock/screens/search_city_screen.dart index b7bd7a76..db172c7f 100644 --- a/lib/clock/screens/search_city_screen.dart +++ b/lib/clock/screens/search_city_screen.dart @@ -1,8 +1,7 @@ import 'package:clock_app/navigation/widgets/app_top_bar.dart'; import 'package:flutter/material.dart'; - import 'package:sqflite/sqflite.dart'; - +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:clock_app/common/utils/list_storage.dart'; import 'package:clock_app/common/data/paths.dart'; import 'package:clock_app/clock/widgets/timezone_search_card.dart'; @@ -77,7 +76,7 @@ class _SearchCityScreenState extends State { focusedBorder: const OutlineInputBorder(borderSide: BorderSide.none), fillColor: Colors.transparent, - hintText: 'Search for a city', + hintText: AppLocalizations.of(context)!.searchCityPlaceholder, hintStyle: Theme.of(context).textTheme.bodyLarge, ), textAlignVertical: TextAlignVertical.center, diff --git a/lib/clock/widgets/timezone_card.dart b/lib/clock/widgets/timezone_card.dart index 6851d53e..f06be9d5 100644 --- a/lib/clock/widgets/timezone_card.dart +++ b/lib/clock/widgets/timezone_card.dart @@ -1,11 +1,11 @@ import 'package:clock_app/clock/types/city.dart'; -import 'package:clock_app/clock/widgets/timezone_card_content.dart'; import 'package:clock_app/common/utils/popup_action.dart'; import 'package:clock_app/common/widgets/card_edit_menu.dart'; import 'package:clock_app/common/widgets/clock/clock.dart'; import 'package:flutter/material.dart'; import 'package:timer_builder/timer_builder.dart'; import 'package:timezone/timezone.dart' as timezone; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class TimeZoneCard extends StatelessWidget { TimeZoneCard({ @@ -28,15 +28,18 @@ class TimeZoneCard extends StatelessWidget { return n.toStringAsFixed(n.truncateToDouble() == n ? 0 : 1); } - String _getOffsetDescription() { + String _getOffsetDescription(BuildContext context) { DateTime currentTime = DateTime.now(); DateTime cityTime = timezone.TZDateTime.now(_timezoneLocation); String hourDifference = _formatTimeOffset(_offset.abs()); - String hourLabel = _offset == 1 ? 'h' : 'h'; String relativeLabel = _offset < 0 ? 'behind' : 'ahead'; - String differentOffsetLabel = '$hourDifference$hourLabel $relativeLabel'; - String offsetLabel = _offset != 0 ? differentOffsetLabel : 'Same time'; + String differentOffsetLabel = AppLocalizations.of(context)! + .relativeTime(hourDifference, relativeLabel); + // '$hourDifference$hourLabel $relativeLabel'; + String offsetLabel = _offset != 0 + ? differentOffsetLabel + : AppLocalizations.of(context)!.sameTime; String differentDayLabel = currentTime.day < cityTime.day ? ' (next day)' @@ -89,7 +92,7 @@ class TimeZoneCard extends StatelessWidget { const Duration(seconds: 1), builder: (context) { return Text( - _getOffsetDescription(), + _getOffsetDescription(context), style: textTheme.bodyMedium?.copyWith( height: 0.5, color: colorScheme.onSurface.withOpacity(0.8)), diff --git a/lib/clock/widgets/timezone_search_card.dart b/lib/clock/widgets/timezone_search_card.dart index 6510f82e..5cbe33f9 100644 --- a/lib/clock/widgets/timezone_search_card.dart +++ b/lib/clock/widgets/timezone_search_card.dart @@ -6,6 +6,7 @@ import 'package:clock_app/common/widgets/clock/clock.dart'; import 'package:flutter/material.dart'; import 'package:timer_builder/timer_builder.dart'; import 'package:timezone/timezone.dart' as timezone; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class TimeZoneSearchCard extends StatelessWidget { TimeZoneSearchCard( @@ -23,6 +24,9 @@ class TimeZoneSearchCard extends StatelessWidget { @override Widget build(BuildContext context) { + final gmtOffset = timezoneLocation.currentTimeZone.offset; + final gmtOffsetHour = gmtOffset / 3600000; + final gmtOffsetMinutes = (gmtOffset % 3600000) / 60000; Color? textColor = disabled ? Theme.of(context).colorScheme.onBackground.withOpacity(0.6) : null; @@ -34,7 +38,8 @@ class TimeZoneSearchCard extends StatelessWidget { ScaffoldMessenger.of(context).removeCurrentSnackBar(); if (disabled) { - showSnackBar(context, 'This city is already in your favorites.'); + showSnackBar( + context, AppLocalizations.of(context)!.cityAlreadyInFavorites); } else { onTap(); } @@ -83,6 +88,13 @@ class TimeZoneSearchCard extends StatelessWidget { scale: 0.3, color: textColor, ), + const SizedBox(height: 4), + Text( + 'GMT ${gmtOffset > 0 ? '+' : '-'}${gmtOffsetHour.abs().toStringAsFixed(0).padLeft(2, '0')}:${gmtOffsetMinutes.toStringAsFixed(0).padLeft(2, '0')}', + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: textColor, + ), + ), ], ), ], diff --git a/lib/common/data/weekdays.dart b/lib/common/data/weekdays.dart index 746fe87a..7d507263 100644 --- a/lib/common/data/weekdays.dart +++ b/lib/common/data/weekdays.dart @@ -1,11 +1,19 @@ import 'package:clock_app/common/types/weekday.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -const List weekdays = [ - Weekday(1, 'M', 'Mon'), - Weekday(2, 'T', 'Tue'), - Weekday(3, 'W', 'Wed'), - Weekday(4, 'T', 'Thu'), - Weekday(5, 'F', 'Fri'), - Weekday(6, 'S', 'Sat'), - Weekday(7, 'S', 'Sun'), +List weekdays = [ + Weekday(1, (context) => AppLocalizations.of(context)!.mondayLetter, + (context) => AppLocalizations.of(context)!.mondayShort), + Weekday(2, (context) => AppLocalizations.of(context)!.tuesdayLetter, + (context) => AppLocalizations.of(context)!.tuesdayShort), + Weekday(3, (context) => AppLocalizations.of(context)!.wednesdayLetter, + (context) => AppLocalizations.of(context)!.wednesdayShort), + Weekday(4, (context) => AppLocalizations.of(context)!.thursdayLetter, + (context) => AppLocalizations.of(context)!.thursdayShort), + Weekday(5, (context) => AppLocalizations.of(context)!.fridayLetter, + (context) => AppLocalizations.of(context)!.fridayShort), + Weekday(6, (context) => AppLocalizations.of(context)!.saturdayLetter, + (context) => AppLocalizations.of(context)!.saturdayShort), + Weekday(7, (context) => AppLocalizations.of(context)!.sundayLetter, + (context) => AppLocalizations.of(context)!.sundayShort), ]; diff --git a/lib/common/logic/show_select.dart b/lib/common/logic/show_select.dart index d6d8d159..b060d6c8 100644 --- a/lib/common/logic/show_select.dart +++ b/lib/common/logic/show_select.dart @@ -1,14 +1,18 @@ +import 'package:clock_app/common/types/popup_action.dart'; import 'package:clock_app/common/types/select_choice.dart'; import 'package:clock_app/common/widgets/fields/select_field/select_bottom_sheet.dart'; import 'package:flutter/material.dart'; Future showSelectBottomSheet( - BuildContext context, void Function(List? indices) onChanged, - {required bool multiSelect, - required String title, - required String? description, - required List choices, - required List initialSelectedIndices}) async { + BuildContext context, + void Function(List? indices) onChanged, { + required bool multiSelect, + required String title, + required String? description, + required List Function() getChoices, + required List Function() getCurrentSelectedIndices, + List actions = const [], +}) async { List? selectedIndices; await showModalBottomSheet>( @@ -16,7 +20,8 @@ Future showSelectBottomSheet( isScrollControlled: true, enableDrag: true, builder: (BuildContext context) { - List currentSelectedIndices = initialSelectedIndices; + List currentSelectedIndices = getCurrentSelectedIndices(); + List choices = getChoices(); return StatefulBuilder( builder: (BuildContext context, StateSetter setState) { void handleSelect(List indices) { @@ -34,8 +39,7 @@ Future showSelectBottomSheet( } else { if (indices.length == 1) { currentSelectedIndices = [indices[0]]; - } - else{ + } else { debugPrint("Too many indices"); } } @@ -53,6 +57,11 @@ Future showSelectBottomSheet( currentSelectedIndices: currentSelectedIndices, onSelect: handleSelect, multiSelect: multiSelect, + actions: actions, + reload: () => setState(() { + choices = getChoices(); + currentSelectedIndices = getCurrentSelectedIndices(); + }), ); }, ); diff --git a/lib/common/logic/tags.dart b/lib/common/logic/tags.dart index 8a532224..0de51c58 100644 --- a/lib/common/logic/tags.dart +++ b/lib/common/logic/tags.dart @@ -4,6 +4,6 @@ import 'package:clock_app/settings/types/setting.dart'; List> getTagOptions() { return loadListSync("tags") - .map((tag) => SelectSettingOption(tag.name, tag)) + .map((tag) => SelectSettingOption((context)=>tag.name, tag)) .toList(); } diff --git a/lib/common/types/list_filter.dart b/lib/common/types/list_filter.dart index f0d04e66..7b7abe59 100644 --- a/lib/common/types/list_filter.dart +++ b/lib/common/types/list_filter.dart @@ -1,25 +1,29 @@ import 'package:clock_app/common/types/list_item.dart'; import 'package:clock_app/common/utils/debug.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class ListSortOption { - final String name; - final String abbreviation; + final String Function(BuildContext) getLocalizedName; + // final String abbreviation; final int Function(Item, Item) sortFunction; - const ListSortOption(this.name, this.abbreviation, this.sortFunction); + String Function(BuildContext) get displayName => getLocalizedName; + + const ListSortOption( + this.getLocalizedName, this.sortFunction); } abstract class ListFilterItem { bool Function(Item) get filterFunction; - String get displayName; + String Function(BuildContext) get displayName; bool get isActive; void reset(); } ListFilter defaultFilter() { return ListFilter( - 'All', + (context) => AppLocalizations.of(context)!.allFilter, (item) => true, id: -1, ); @@ -27,11 +31,12 @@ ListFilter defaultFilter() { class ListFilter extends ListFilterItem { final int _id; - final String name; + final String Function(BuildContext) getLocalizedName; bool isSelected = false; final bool Function(Item) _filterFunction; - ListFilter(this.name, bool Function(Item) filterFunction, {int? id}) + ListFilter(this.getLocalizedName, bool Function(Item) filterFunction, + {int? id}) : _id = id ?? UniqueKey().hashCode, _filterFunction = filterFunction; @@ -44,7 +49,7 @@ class ListFilter extends ListFilterItem { } @override - String get displayName => name; + String Function(BuildContext) get displayName => getLocalizedName; @override bool get isActive => isSelected; @@ -56,7 +61,7 @@ class ListFilter extends ListFilterItem { } class ListFilterSearch extends ListFilterItem { - final String name; + final String Function(BuildContext) getLocalizedName; String searchText = ''; @override bool Function(Item) get filterFunction { @@ -66,9 +71,9 @@ class ListFilterSearch extends ListFilterItem { // return (Item item) => item.searchText.contains(searchText); } - ListFilterSearch(this.name); + ListFilterSearch(this.getLocalizedName); @override - String get displayName => name; + String Function(BuildContext) get displayName => getLocalizedName; @override bool get isActive => false; @@ -98,10 +103,10 @@ abstract class FilterMultiSelect class ListFilterMultiSelect extends FilterMultiSelect { - final String name; + final String Function(BuildContext) getLocalizedName; @override final List> filters; - ListFilterMultiSelect(this.name, this.filters); + ListFilterMultiSelect(this.getLocalizedName, this.filters); @override List get selectedIndices => filters @@ -121,7 +126,7 @@ class ListFilterMultiSelect } @override - String get displayName => name; + String Function(BuildContext) get displayName => getLocalizedName; @override bool get isActive => filters.any((filter) => filter.isSelected); @@ -136,13 +141,14 @@ class ListFilterMultiSelect class DynamicListFilterMultiSelect extends FilterMultiSelect { - final String name; + final String Function(BuildContext) getLocalizedName; final List> Function() getFilters; List selectedIds; - DynamicListFilterMultiSelect(this.name, this.getFilters) : selectedIds = []; + DynamicListFilterMultiSelect(this.getLocalizedName, this.getFilters) + : selectedIds = []; @override @override - String get displayName => name; + String Function(BuildContext) get displayName => getLocalizedName; @override List> get selectedFilters => @@ -199,10 +205,10 @@ abstract class FilterSelect } class ListFilterSelect extends FilterSelect { - final String name; + final String Function(BuildContext) getLocalizedName; @override final List> filters; - ListFilterSelect(this.name, this.filters) { + ListFilterSelect(this.getLocalizedName, this.filters) { filters.insert(0, defaultFilter()); if (filters.isNotEmpty) { filters[0].isSelected = true; @@ -227,7 +233,7 @@ class ListFilterSelect extends FilterSelect { } @override - String get displayName => name; + String Function(BuildContext) get displayName => getLocalizedName; @override bool get isActive => !filters[0].isSelected; @@ -240,10 +246,11 @@ class ListFilterSelect extends FilterSelect { class DynamicListFilterSelect extends FilterSelect { - final String name; + final String Function(BuildContext) getLocalizedName; final List> Function() getFilters; int selectedId; - DynamicListFilterSelect(this.name, this.getFilters) : selectedId = -1; + DynamicListFilterSelect(this.getLocalizedName, this.getFilters) + : selectedId = -1; @override List> get filters { @@ -281,7 +288,7 @@ class DynamicListFilterSelect } @override - String get displayName => name; + String Function(BuildContext) get displayName => getLocalizedName; @override bool get isActive => selectedIndex != 0; diff --git a/lib/common/types/popup_action.dart b/lib/common/types/popup_action.dart index 115b0862..9b994122 100644 --- a/lib/common/types/popup_action.dart +++ b/lib/common/types/popup_action.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; -class PopupAction { +class MenuAction { IconData icon; String name; - Function action; + Function(BuildContext context) action; Color? color; - PopupAction(this.name, this.action, this.icon, [this.color]); + MenuAction(this.name, this.action, this.icon, [this.color]); } diff --git a/lib/common/types/weekday.dart b/lib/common/types/weekday.dart index 1ca08af0..06160441 100644 --- a/lib/common/types/weekday.dart +++ b/lib/common/types/weekday.dart @@ -1,7 +1,9 @@ +import 'package:flutter/material.dart'; + class Weekday { final int id; - final String abbreviation; - final String displayName; + final String Function(BuildContext) getAbbreviation; + final String Function(BuildContext) getDisplayName; - const Weekday(this.id, this.abbreviation, this.displayName); + const Weekday(this.id, this.getAbbreviation, this.getDisplayName); } diff --git a/lib/common/utils/popup_action.dart b/lib/common/utils/popup_action.dart index 32c321c9..f3776d56 100644 --- a/lib/common/utils/popup_action.dart +++ b/lib/common/utils/popup_action.dart @@ -1,11 +1,13 @@ import 'package:clock_app/common/types/popup_action.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -PopupAction getDeletePopupAction(BuildContext context, Function callback) { - return PopupAction("Delete", callback, Icons.delete_rounded, + +MenuAction getDeletePopupAction(BuildContext context, void Function() callback) { + return MenuAction(AppLocalizations.of(context)!.deleteButton, (context) => callback(), Icons.delete_rounded, Theme.of(context).colorScheme.error); } -PopupAction getDuplicatePopupAction(Function callback) { - return PopupAction("Duplicate", callback, Icons.copy_rounded); +MenuAction getDuplicatePopupAction(BuildContext context, void Function() callback) { + return MenuAction(AppLocalizations.of(context)!.duplicateButton, (context)=>callback, Icons.copy_rounded); } diff --git a/lib/common/utils/ringtones.dart b/lib/common/utils/ringtones.dart index 5a0a90eb..3a38aef5 100644 --- a/lib/common/utils/ringtones.dart +++ b/lib/common/utils/ringtones.dart @@ -4,6 +4,6 @@ import 'package:clock_app/settings/types/setting.dart'; List> getRingtoneOptions() { return loadListSync("ringtones") - .map((ringtone) => SelectSettingOption(ringtone.name, ringtone)) + .map((ringtone) => SelectSettingOption((context)=>ringtone.name, ringtone)) .toList(); } diff --git a/lib/common/utils/weekday_utils.dart b/lib/common/utils/weekday_utils.dart index 24c1996a..66eaac36 100644 --- a/lib/common/utils/weekday_utils.dart +++ b/lib/common/utils/weekday_utils.dart @@ -1,12 +1,12 @@ import 'package:clock_app/common/data/weekdays.dart'; import 'package:clock_app/common/types/weekday.dart'; -bool weekdaysContains(List alarmWeekdays, String name) { +bool weekdaysContains(List alarmWeekdays, int id) { Weekday weekday = - weekdays.firstWhere((weekday) => weekday.displayName == name); + weekdays.firstWhere((weekday) => weekday.id == id); return alarmWeekdays.contains(weekday); } -bool weekdaysContainsAll(List alarmWeekdays, List names) { - return names.every((name) => weekdaysContains(alarmWeekdays, name)); +bool weekdaysContainsAll(List alarmWeekdays, List ids) { + return ids.every((id) => weekdaysContains(alarmWeekdays, id)); } diff --git a/lib/common/widgets/action_pane.dart b/lib/common/widgets/action_pane.dart index b428218d..2773c304 100644 --- a/lib/common/widgets/action_pane.dart +++ b/lib/common/widgets/action_pane.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + ActionPane getDeleteActionPane(VoidCallback onDelete, BuildContext context) { final theme = Theme.of(context); @@ -18,7 +20,7 @@ ActionPane getDeleteActionPane(VoidCallback onDelete, BuildContext context) { children: [ Icon(Icons.delete, color: colorScheme.onError), const SizedBox(height: 4), - Text('Delete', + Text(AppLocalizations.of(context)!.deleteButton, style: textTheme.titleSmall?.copyWith( color: colorScheme.onError, )), @@ -49,7 +51,7 @@ ActionPane getDuplicateActionPane( children: [ Icon(Icons.copy_rounded, color: colorScheme.onPrimary), const SizedBox(height: 4), - Text('Duplicate', + Text(AppLocalizations.of(context)!.duplicateButton, style: textTheme.titleSmall?.copyWith( color: colorScheme.onPrimary, )), diff --git a/lib/common/widgets/card_edit_menu.dart b/lib/common/widgets/card_edit_menu.dart index 4ba40006..efa2432d 100644 --- a/lib/common/widgets/card_edit_menu.dart +++ b/lib/common/widgets/card_edit_menu.dart @@ -9,7 +9,7 @@ class CardEditMenu extends StatelessWidget { required this.actions, }); - final List actions; + final List actions; // final GlobalKey _buttonKey = GlobalKey(); List> getItems() { @@ -24,10 +24,10 @@ class CardEditMenu extends StatelessWidget { return items; } - void onSelected(String action) { + void onSelected(BuildContext context, String action) { for (var item in actions) { if (item.name == action) { - item.action(); + item.action(context); } } } @@ -43,7 +43,7 @@ class CardEditMenu extends StatelessWidget { color: colorScheme.onSurface, ), padding: EdgeInsets.zero, - onSelected: onSelected, + onSelected: (action) => onSelected(context, action), itemBuilder: (BuildContext context) => getItems(), ); } diff --git a/lib/common/widgets/clock/time_display.dart b/lib/common/widgets/clock/time_display.dart index d2c9021e..829ef769 100644 --- a/lib/common/widgets/clock/time_display.dart +++ b/lib/common/widgets/clock/time_display.dart @@ -4,6 +4,7 @@ import 'package:intl/intl.dart'; class TimeDisplay extends StatelessWidget { const TimeDisplay({ + super.key, required this.format, required this.fontSize, @@ -20,7 +21,8 @@ class TimeDisplay extends StatelessWidget { @override Widget build(BuildContext context) { - String formattedTime = DateFormat(format).format(dateTime); + Locale locale = Localizations.localeOf(context); + String formattedTime = DateFormat(format, locale.languageCode).format(dateTime); return Text( formattedTime, style: Theme.of(context).textTheme.displaySmall?.copyWith( diff --git a/lib/common/widgets/color_picker/picker_selector.dart b/lib/common/widgets/color_picker/picker_selector.dart index cdfe5219..eb520e88 100644 --- a/lib/common/widgets/color_picker/picker_selector.dart +++ b/lib/common/widgets/color_picker/picker_selector.dart @@ -51,7 +51,7 @@ class PickerSelector extends StatelessWidget { }, options: options.where((option) => pickers[option.value]!).toList(), square: false, - innerPadding: 16, + innerPadding: 12, ), ), ); diff --git a/lib/common/widgets/customize_screen.dart b/lib/common/widgets/customize_screen.dart index 394efe82..ec581693 100644 --- a/lib/common/widgets/customize_screen.dart +++ b/lib/common/widgets/customize_screen.dart @@ -1,6 +1,7 @@ import 'package:clock_app/common/types/list_item.dart'; import 'package:clock_app/navigation/widgets/app_top_bar.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class CustomizeState { bool isSaved = false; @@ -47,7 +48,7 @@ class _CustomizeScreenState Navigator.pop(context); }, child: Text( - "Cancel", + AppLocalizations.of(context)!.cancelButton, style: TextStyle( color: colorScheme.onSurface.withOpacity(0.6), ), @@ -61,7 +62,7 @@ class _CustomizeScreenState _isSaved = true; Navigator.pop(context, _item); }, - child: const Text("Save"), + child: Text(AppLocalizations.of(context)!.saveButton), ), ) ]), @@ -76,21 +77,21 @@ class _CustomizeScreenState builder: (buildContext) { return AlertDialog( actionsPadding: const EdgeInsets.only(bottom: 6, right: 10), - content: const Text("Do you want to leave without saving?"), + content: Text(AppLocalizations.of(context)!.saveReminderAlert), actions: [ TextButton( onPressed: () { Navigator.pop(context, false); }, - child: Text("No", + child: Text(AppLocalizations.of(context)!.noButton, style: TextStyle(color: colorScheme.primary)), ), TextButton( onPressed: () { Navigator.pop(context, true); }, - child: - Text("Yes", style: TextStyle(color: colorScheme.error)), + child: Text(AppLocalizations.of(context)!.yesButton, + style: TextStyle(color: colorScheme.error)), ), ], ); diff --git a/lib/common/widgets/fields/color_bottom_sheet.dart b/lib/common/widgets/fields/color_bottom_sheet.dart index 9cc98718..45efe10b 100644 --- a/lib/common/widgets/fields/color_bottom_sheet.dart +++ b/lib/common/widgets/fields/color_bottom_sheet.dart @@ -10,12 +10,14 @@ class ColorBottomSheet extends StatefulWidget { this.description, required this.value, required this.onChange, + this.enableOpacity = false, }); final String title; final String? description; final Color value; final void Function(Color)? onChange; + final bool enableOpacity; @override State createState() => _ColorBottomSheetState(); @@ -79,7 +81,7 @@ class _ColorBottomSheetState extends State { ), // const SizedBox(height: 16.0), ColorPicker( - wheelDiameter: MediaQuery.of(context).size.width - 8, + wheelDiameter: MediaQuery.of(context).size.width - (widget.enableOpacity ? 64 : 32), color: _color, onColorChanged: (Color color) => setState(() { _color = color; @@ -103,6 +105,9 @@ class _ColorBottomSheetState extends State { style: textTheme.titleSmall ?.copyWith(color: colorScheme.onSurface)), showColorCode: true, + enableOpacity: widget.enableOpacity, + opacityTrackHeight: 20, + opacityThumbRadius: 14, copyPasteBehavior: const ColorPickerCopyPasteBehavior( copyFormat: ColorPickerCopyFormat.hexRRGGBB), customPickerSelectBuilder: diff --git a/lib/common/widgets/fields/color_field.dart b/lib/common/widgets/fields/color_field.dart index cb2539f7..1719ff1b 100644 --- a/lib/common/widgets/fields/color_field.dart +++ b/lib/common/widgets/fields/color_field.dart @@ -3,15 +3,18 @@ import 'package:clock_app/common/widgets/fields/color_bottom_sheet.dart'; import 'package:flutter/material.dart'; class ColorField extends StatefulWidget { - const ColorField( - {super.key, - required this.value, - required this.onChange, - required this.name}); + const ColorField({ + super.key, + required this.value, + required this.onChange, + required this.name, + this.enableOpacity = false, + }); final String name; final Color value; final void Function(Color value)? onChange; + final bool enableOpacity; @override State createState() => _ColorFieldState(); @@ -31,6 +34,8 @@ class _ColorFieldState extends State { description: "", value: widget.value, onChange: widget.onChange, + enableOpacity: widget.enableOpacity, + ); }, ); diff --git a/lib/common/widgets/fields/select_field/field_cards/text_field_card.dart b/lib/common/widgets/fields/select_field/field_cards/text_field_card.dart index ba63c466..49d4d104 100644 --- a/lib/common/widgets/fields/select_field/field_cards/text_field_card.dart +++ b/lib/common/widgets/fields/select_field/field_cards/text_field_card.dart @@ -11,21 +11,28 @@ class TextFieldCard extends StatelessWidget { Widget build(BuildContext context) { return Row( children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: Theme.of(context).textTheme.headlineMedium, - ), - const SizedBox(height: 4.0), - Text( - choice.name, - style: Theme.of(context).textTheme.bodyMedium, - ), - ], + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: Theme.of(context).textTheme.headlineMedium, + maxLines: 2, + overflow: TextOverflow.ellipsis, + softWrap: false, + ), + const SizedBox(height: 4.0), + Text( + choice.name, + style: Theme.of(context).textTheme.bodyMedium, + maxLines: 1, + overflow: TextOverflow.ellipsis, + softWrap: false, + ), + ], + ), ), - const Spacer(), Icon( Icons.keyboard_arrow_down_rounded, color: Theme.of(context).colorScheme.onBackground.withOpacity(0.6), diff --git a/lib/common/widgets/fields/select_field/select_bottom_sheet.dart b/lib/common/widgets/fields/select_field/select_bottom_sheet.dart index 6228479d..a19cdf19 100644 --- a/lib/common/widgets/fields/select_field/select_bottom_sheet.dart +++ b/lib/common/widgets/fields/select_field/select_bottom_sheet.dart @@ -1,9 +1,12 @@ import 'package:clock_app/common/types/file_item.dart'; +import 'package:clock_app/common/types/popup_action.dart'; import 'package:clock_app/common/types/select_choice.dart'; import 'package:clock_app/common/widgets/fields/select_field/option_cards/audio_option_card.dart'; import 'package:clock_app/common/widgets/fields/select_field/option_cards/color_option_card.dart'; import 'package:clock_app/common/widgets/fields/select_field/option_cards/text_option_card.dart'; +import 'package:clock_app/icons/flux_icons.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class SelectBottomSheet extends StatelessWidget { const SelectBottomSheet({ @@ -13,7 +16,9 @@ class SelectBottomSheet extends StatelessWidget { required this.choices, required this.currentSelectedIndices, required this.onSelect, + this.actions = const [], this.multiSelect = false, + this.reload, }); final String title; @@ -22,6 +27,8 @@ class SelectBottomSheet extends StatelessWidget { final List currentSelectedIndices; final bool multiSelect; final void Function(List) onSelect; + final List actions; + final Function? reload; Widget _getOptionCard() { if (choices[0].value is Color) { @@ -101,14 +108,33 @@ class SelectBottomSheet extends StatelessWidget { ), const SizedBox(height: 12.0), Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), + padding: const EdgeInsets.symmetric(horizontal: 20.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - title, - style: textTheme.titleMedium?.copyWith( - color: colorScheme.onSurface.withOpacity(0.6)), + Row( + children: [ + // Expanded(child: Container()), + if (actions.isNotEmpty) const SizedBox(width: 8), + Expanded( + child: Text( + title, + style: textTheme.titleMedium?.copyWith( + color: colorScheme.onSurface.withOpacity(0.6)), + textAlign: actions.isEmpty ? TextAlign.center : null, + ), + ), + for (var action in actions) + IconButton( + icon: Icon(action.icon, + color: action.color ?? colorScheme.primary), + onPressed: () async { + // Navigator.pop(context, currentSelectedIndices); + await action.action(context); + reload?.call(); + }, + ), + ], ), if (description != null) const SizedBox(height: 8.0), if (description != null) @@ -120,37 +146,55 @@ class SelectBottomSheet extends StatelessWidget { ], ), ), - // const SizedBox(height: 16.0), + // Row( + // children: [ + // Icon(FluxIcons.add), + // Text(AppLocalizations.of(context)!.addButton, + // style: textTheme.labelMedium + // ?.copyWith(color: colorScheme.primary)), + // + // ], + // ), + const SizedBox(height: 12.0), Flexible( child: _getOptionCard(), ), // if (multiSelect) const SizedBox(height: 8.0), if (multiSelect) Padding( - padding: const EdgeInsets.only(left: 16.0, right:16.0, bottom: 4.0), - child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Row( + padding: + const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 4.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - IconButton( - onPressed: () { - onSelect([]); - }, - icon: Icon(Icons.clear_rounded, color: colorScheme.primary), - ), - IconButton( - onPressed: () { - onSelect([for (var i = 0; i < choices.length; i += 1) i]); - }, - icon: Icon(Icons.select_all_rounded, color: colorScheme.primary), + Row( + children: [ + IconButton( + onPressed: () { + onSelect([]); + }, + icon: Icon(Icons.clear_rounded, + color: colorScheme.primary), + ), + IconButton( + onPressed: () { + onSelect([ + for (var i = 0; i < choices.length; i += 1) i + ]); + }, + icon: Icon(Icons.select_all_rounded, + color: colorScheme.primary), + ), + ], ), - ], - ), - TextButton(onPressed: (){ - Navigator.of(context).pop(); - }, child: Text('Save', - style: textTheme.labelMedium?.copyWith( - color:colorScheme.primary))), - ]), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text(AppLocalizations.of(context)!.saveButton, + style: textTheme.labelMedium + ?.copyWith(color: colorScheme.primary))), + ]), ) ], ), diff --git a/lib/common/widgets/fields/select_field/select_field.dart b/lib/common/widgets/fields/select_field/select_field.dart index 8c66e97d..a3cb3ada 100644 --- a/lib/common/widgets/fields/select_field/select_field.dart +++ b/lib/common/widgets/fields/select_field/select_field.dart @@ -1,5 +1,6 @@ import 'package:clock_app/common/logic/show_select.dart'; import 'package:clock_app/common/types/file_item.dart'; +import 'package:clock_app/common/types/popup_action.dart'; import 'package:clock_app/common/types/select_choice.dart'; import 'package:clock_app/common/types/tag.dart'; import 'package:clock_app/common/widgets/fields/select_field/field_cards/audio_field_card.dart'; @@ -11,34 +12,38 @@ import 'package:flutter/material.dart'; class SelectField extends StatefulWidget { const SelectField({ super.key, - required this.selectedIndices, + required this.getSelectedIndices, required this.title, this.description, - required this.choices, + required this.getChoices, required this.onChanged, this.multiSelect = false, + this.actions = const [], }); - final List selectedIndices; + final List Function() getSelectedIndices; final String title; final String? description; final bool multiSelect; - final List choices; + final List Function() getChoices; final void Function(List indices) onChanged; + final List actions; @override State createState() => _SelectFieldState(); } class _SelectFieldState extends State { - Widget _getFieldCard() { + Widget _getFieldCard(List choices, List selectedIndices) { + + if (widget.multiSelect) { - List choices = - widget.selectedIndices.map((index) => widget.choices[index]).toList(); + List selectedChoices = + selectedIndices.map((index) => choices[index]).toList(); if (choices.isNotEmpty && choices[0].value.runtimeType == Tag) { return MultiSelectFieldCard( title: widget.title, - choices: choices + choices: selectedChoices .map((e) => SelectChoice( name: e.name, value: e.value, @@ -48,7 +53,7 @@ class _SelectFieldState extends State { } return MultiSelectFieldCard(title: widget.title, choices: choices); } else { - SelectChoice choice = widget.choices[widget.selectedIndices[0]]; + SelectChoice choice = choices[selectedIndices[0]]; if (choice.value is Color) { return ColorFieldCard( choice: SelectChoice( @@ -76,24 +81,31 @@ class _SelectFieldState extends State { @override Widget build(BuildContext context) { + List choices = widget.getChoices(); + List selectedIndices = widget.getSelectedIndices(); + void showSelect(List? selectedIndices) async { setState(() { - widget.onChanged(selectedIndices ?? widget.selectedIndices); + widget.onChanged(selectedIndices ?? widget.getSelectedIndices()); }); } return Material( color: Colors.transparent, child: InkWell( - onTap: () => showSelectBottomSheet(context, showSelect, - title: widget.title, - description: widget.description, - choices: widget.choices, - initialSelectedIndices: widget.selectedIndices, - multiSelect: widget.multiSelect), + onTap: () => showSelectBottomSheet( + context, + showSelect, + title: widget.title, + description: widget.description, + getChoices: widget.getChoices, + getCurrentSelectedIndices: widget.getSelectedIndices, + multiSelect: widget.multiSelect, + actions: widget.actions, + ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), - child: _getFieldCard(), + child: _getFieldCard(choices, selectedIndices), ), ), ); diff --git a/lib/common/widgets/list/custom_list_view.dart b/lib/common/widgets/list/custom_list_view.dart index c84e61df..9e4f3fe2 100644 --- a/lib/common/widgets/list/custom_list_view.dart +++ b/lib/common/widgets/list/custom_list_view.dart @@ -2,7 +2,6 @@ import 'package:clock_app/common/logic/get_list_filter_chips.dart'; import 'package:clock_app/common/types/list_controller.dart'; import 'package:clock_app/common/types/list_filter.dart'; import 'package:clock_app/common/types/list_item.dart'; -import 'package:clock_app/common/utils/json_serialize.dart'; import 'package:clock_app/common/utils/reorderable_list_decorator.dart'; import 'package:clock_app/common/widgets/list/delete_alert_dialogue.dart'; import 'package:clock_app/common/widgets/list/list_filter_chip.dart'; @@ -10,6 +9,7 @@ import 'package:clock_app/common/widgets/list/list_item_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:great_list_view/great_list_view.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; typedef ItemCardBuilder = Widget Function( BuildContext context, @@ -169,10 +169,12 @@ class _CustomListViewState }); final deletedItems = List.from(initialList - .where((element) => currentList.where((e) => e.id == element.id).isEmpty) + .where( + (element) => currentList.where((e) => e.id == element.id).isEmpty) .toList()); final addedItems = List.from(currentList - .where((element) => initialList.where((e) => e.id == element.id).isEmpty) + .where( + (element) => initialList.where((e) => e.id == element.id).isEmpty) .toList()); for (var deletedItem in deletedItems) { @@ -333,7 +335,7 @@ class _CustomListViewState widgets.add(ListFilterActionChip( actions: [ ListFilterAction( - name: "Clear all filters", + name: AppLocalizations.of(context)!.clearFiltersAction, icon: Icons.clear_rounded, action: () { for (var filter in widget.listFilters) { @@ -351,7 +353,7 @@ class _CustomListViewState .toList()), )), ListFilterAction( - name: "Delete all filtered items", + name: AppLocalizations.of(context)!.deleteAllFilteredAction, icon: Icons.delete_rounded, color: colorScheme.error, action: () async { @@ -378,7 +380,9 @@ class _CustomListViewState ListSortChip( selectedIndex: selectedSortIndex, sortOptions: [ - ListSortOption("Default", "", (a, b) => 0), + ListSortOption( + (context) => AppLocalizations.of(context)!.defaultLabel, + (a, b) => 0), ...widget.sortOptions, ], onChange: (index) => setState(() { diff --git a/lib/common/widgets/list/list_filter_chip.dart b/lib/common/widgets/list/list_filter_chip.dart index 8a3307df..38bb2890 100644 --- a/lib/common/widgets/list/list_filter_chip.dart +++ b/lib/common/widgets/list/list_filter_chip.dart @@ -3,9 +3,9 @@ import 'package:clock_app/common/types/list_filter.dart'; import 'package:clock_app/common/types/list_item.dart'; import 'package:clock_app/common/types/select_choice.dart'; import 'package:clock_app/common/widgets/card_container.dart'; -import 'package:clock_app/common/widgets/card_edit_menu.dart'; import 'package:clock_app/common/widgets/list/action_bottom_sheet.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class ListFilterChip extends StatelessWidget { const ListFilterChip({ @@ -32,7 +32,7 @@ class ListFilterChip extends StatelessWidget { child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), child: Text( - listFilter.name, + listFilter.displayName(context), style: textTheme.headlineSmall?.copyWith( color: listFilter.isSelected ? colorScheme.onPrimary @@ -61,7 +61,7 @@ class ListFilterActionChip extends StatelessWidget { enableDrag: true, builder: (BuildContext context) { return ActionBottomSheet( - title: "Filter Actions", + title: AppLocalizations.of(context)!.filterActions, actions: actions, // description: description, ); @@ -85,7 +85,8 @@ class ListFilterActionChip extends StatelessWidget { child: Row( children: [ Padding( - padding: const EdgeInsets.only(left: 8.0, right: 6.0, top:6.0, bottom: 6.0), + padding: const EdgeInsets.only( + left: 8.0, right: 6.0, top: 6.0, bottom: 6.0), child: Icon( Icons.filter_list_rounded, color: colorScheme.onPrimary, @@ -130,12 +131,13 @@ class ListFilterSelectChip extends StatelessWidget { selectedIndices?[0] ?? listFilter.selectedIndex; onChange(); }, - title: listFilter.displayName, + title: listFilter.displayName(context), description: "", - choices: listFilter.filters - .map((e) => SelectChoice(name: e.name, value: e.id)) + getChoices: () => listFilter.filters + .map((e) => + SelectChoice(name: e.displayName(context), value: e.id)) .toList(), - initialSelectedIndices: [listFilter.selectedIndex], + getCurrentSelectedIndices: () => [listFilter.selectedIndex], multiSelect: false); } @@ -149,8 +151,8 @@ class ListFilterSelectChip extends StatelessWidget { top: 8.0, bottom: 8.0, left: 16.0, right: 2.0), child: Text( isFirstSelected - ? listFilter.displayName - : listFilter.selectedFilter.name, + ? listFilter.displayName(context) + : listFilter.selectedFilter.displayName(context), style: textTheme.headlineSmall?.copyWith( color: isFirstSelected ? colorScheme.onSurface @@ -196,12 +198,13 @@ class ListFilterMultiSelectChip extends StatelessWidget { newSelectedIndices ?? listFilter.selectedIndices; onChange(); }, - title: listFilter.displayName, + title: listFilter.displayName(context), description: "", - choices: listFilter.filters - .map((e) => SelectChoice(name: e.name, value: e.id)) + getChoices: () => listFilter.filters + .map((e) => + SelectChoice(name: e.displayName(context), value: e.id)) .toList(), - initialSelectedIndices: selectedIndices, + getCurrentSelectedIndices: () => selectedIndices, multiSelect: true); } @@ -215,9 +218,9 @@ class ListFilterMultiSelectChip extends StatelessWidget { top: 8.0, bottom: 8.0, left: 16.0, right: 2.0), child: Text( !isSelected - ? listFilter.displayName + ? listFilter.displayName(context) : listFilter.selectedIndices.length == 1 - ? listFilter.selectedFilters[0].name + ? listFilter.selectedFilters[0].displayName(context) : "${listFilter.selectedIndices.length} selected", style: textTheme.headlineSmall?.copyWith( color: isSelected @@ -248,7 +251,8 @@ class ListSortChip extends StatelessWidget { const ListSortChip({ super.key, required this.sortOptions, - required this.onChange, required this.selectedIndex, + required this.onChange, + required this.selectedIndex, }); @override @@ -262,12 +266,13 @@ class ListSortChip extends StatelessWidget { showSelectBottomSheet(context, (List? selectedIndices) { onChange(selectedIndices?[0] ?? selectedIndex); }, - title: "Sort by", + title: AppLocalizations.of(context)!.sortGroup, description: "", - choices: sortOptions - .map((e) => SelectChoice(name: e.name, value: e.name)) + getChoices: () => sortOptions + .map((e) => SelectChoice( + name: e.displayName(context), value: e.getLocalizedName)) .toList(), - initialSelectedIndices: [selectedIndex], + getCurrentSelectedIndices: () => [selectedIndex], multiSelect: false); } @@ -280,18 +285,15 @@ class ListSortChip extends StatelessWidget { padding: const EdgeInsets.only( top: 8.0, bottom: 8.0, left: 16.0, right: 2.0), child: Text( - "Sort${isFirstSelected ? "" : ": ${sortOptions[selectedIndex].abbreviation}"}", - style: textTheme.headlineSmall?.copyWith( - color: colorScheme.onSurface - ), + "${AppLocalizations.of(context)!.sortGroup}${isFirstSelected ? "" : ": ${sortOptions[selectedIndex].displayName(context)}"}", + style: textTheme.headlineSmall + ?.copyWith(color: colorScheme.onSurface), ), ), Padding( padding: const EdgeInsets.only(left: 2.0, right: 8.0), - child: Icon( - Icons.keyboard_arrow_down_rounded, - color:colorScheme.onSurface.withOpacity(0.6) - ), + child: Icon(Icons.keyboard_arrow_down_rounded, + color: colorScheme.onSurface.withOpacity(0.6)), ), ], ), diff --git a/lib/common/widgets/modal.dart b/lib/common/widgets/modal.dart index 5ca669a4..1f66b09c 100644 --- a/lib/common/widgets/modal.dart +++ b/lib/common/widgets/modal.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + class ModalAction { final String title; @@ -53,7 +55,7 @@ class Modal extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( - child: Text('Cancel', + child: Text(AppLocalizations.of(context)!.cancelButton, style: textTheme.labelMedium?.copyWith( color: colorScheme.onBackground.withOpacity(0.6))), onPressed: () { @@ -74,7 +76,7 @@ class Modal extends StatelessWidget { ], TextButton( child: Text( - 'Save', + AppLocalizations.of(context)!.saveButton, style: textTheme.labelMedium?.copyWith( color: isSaveEnabled ? colorScheme.primary diff --git a/lib/common/widgets/popup_menu.dart b/lib/common/widgets/popup_menu.dart deleted file mode 100644 index 913465b5..00000000 --- a/lib/common/widgets/popup_menu.dart +++ /dev/null @@ -1,202 +0,0 @@ -// import 'dart:core'; -// import 'dart:ui'; - -// import 'package:flutter/material.dart'; -// import 'package:popup_menu/src/grid_menu_layout.dart'; -// import 'package:popup_menu/src/list_menu_layout.dart'; -// import 'package:popup_menu/src/menu_config.dart'; -// import 'package:popup_menu/src/menu_layout.dart'; -// import 'package:popup_menu/src/triangle_painter.dart'; -// import 'package:popup_menu/src/utils.dart'; - -// enum MenuType { -// /// 格子 -// grid, - -// /// 单列 -// list -// } - -// typedef MenuClickCallback = void Function(MenuItemProvider item); - -// class CustomPopupMenu { -// OverlayEntry? _entry; -// late List items; - -// /// callback -// final VoidCallback? onDismiss; -// final MenuClickCallback? onClickMenu; -// final VoidCallback? onShow; - -// /// Cannot be null -// BuildContext context; - -// /// It's showing or not. -// bool _isShow = false; -// bool get isShow => _isShow; - -// final MenuConfig config; -// final Size _screenSize = window.physicalSize / window.devicePixelRatio; - -// CustomPopupMenu({ -// required this.context, -// required this.items, -// this.config = const MenuConfig(), -// this.onClickMenu, -// this.onDismiss, -// this.onShow, -// }); - -// MenuLayout? menuLayout; - -// void show({ -// Rect? rect, -// GlobalKey? widgetKey, -// }) { -// assert(rect != null || widgetKey != null, -// "'rect' and 'key' can't be both null"); - -// final attachRect = rect ?? getWidgetGlobalRect(widgetKey!); - -// if (config.type == MenuType.grid) { -// menuLayout = GridMenuLayout( -// config: config, -// items: items, -// onDismiss: dismiss, -// context: context, -// onClickMenu: onClickMenu, -// ); -// } else if (config.type == MenuType.list) { -// menuLayout = ListMenuLayout( -// config: config, -// items: items, -// onDismiss: dismiss, -// context: context, -// onClickMenu: onClickMenu, -// ); -// } - -// _LayoutP layoutp = _calculateOffset( -// context, -// attachRect, -// menuLayout!.width, -// menuLayout!.height, -// ); - -// _entry = OverlayEntry(builder: (context) { -// return build(layoutp, menuLayout!); -// }); - -// Overlay.of(context)!.insert(_entry!); -// _isShow = true; -// onShow?.call(); -// } - -// Widget build(_LayoutP layoutp, MenuLayout menu) { -// return GestureDetector( -// behavior: HitTestBehavior.translucent, -// onTap: () { -// dismiss(); -// }, -// onVerticalDragStart: (DragStartDetails details) { -// dismiss(); -// }, -// onHorizontalDragStart: (DragStartDetails details) { -// dismiss(); -// }, -// child: Material( -// color: Colors.transparent, -// elevation: 2, -// child: Stack( -// children: [ -// // triangle arrow -// Positioned( -// left: layoutp.attachRect.left + -// layoutp.attachRect.width / 2.0 - -// 7.5, -// top: layoutp.isDown -// ? layoutp.offset.dy + layoutp.height -// : layoutp.offset.dy - config.arrowHeight, -// child: CustomPaint( -// size: Size(15.0, config.arrowHeight), -// painter: TrianglePainter( -// isDown: layoutp.isDown, color: config.backgroundColor), -// ), -// ), -// // menu content -// Positioned( -// left: layoutp.offset.dx, -// top: layoutp.offset.dy, -// child: menu.build(), -// ) -// ], -// )), -// ); -// } - -// /// 计算布局位置 -// _LayoutP _calculateOffset( -// BuildContext context, -// Rect attachRect, -// double contentWidth, -// double contentHeight, -// ) { -// double dx = attachRect.left + attachRect.width / 2.0 - contentWidth / 2.0; -// if (dx < 10.0) { -// dx = 10.0; -// } - -// if (dx + contentWidth > _screenSize.width && dx > 10.0) { -// double tempDx = _screenSize.width - contentWidth - 10; -// if (tempDx > 10) { -// dx = tempDx; -// } -// } - -// double dy = attachRect.top - contentHeight; -// bool isDown = false; -// if (dy <= MediaQuery.of(context).padding.top + 10) { -// // The have not enough space above, show menu under the widget. -// dy = config.arrowHeight + attachRect.height + attachRect.top; -// isDown = false; -// } else { -// dy -= config.arrowHeight; -// isDown = true; -// } - -// return _LayoutP( -// width: contentWidth, -// height: contentHeight, -// attachRect: attachRect, -// offset: Offset(dx, dy), -// isDown: isDown, -// ); -// } - -// void dismiss() { -// if (!_isShow) { -// // Remove method should only be called once -// return; -// } - -// _entry?.remove(); -// _isShow = false; -// onDismiss?.call(); -// } -// } - -// class _LayoutP { -// double width; -// double height; -// Offset offset; -// Rect attachRect; -// bool isDown; - -// _LayoutP({ -// required this.width, -// required this.height, -// required this.offset, -// required this.attachRect, -// required this.isDown, -// }); -// } diff --git a/lib/common/widgets/spinner_time_picker.dart b/lib/common/widgets/spinner_time_picker.dart index 5f119da2..5ba2d64b 100644 --- a/lib/common/widgets/spinner_time_picker.dart +++ b/lib/common/widgets/spinner_time_picker.dart @@ -312,6 +312,8 @@ class _TimePickerSpinnerState extends State { @override Widget build(BuildContext context) { + + List contents = [ SizedBox( width: _getItemWidth(), diff --git a/lib/common/widgets/time_picker.dart b/lib/common/widgets/time_picker.dart index 69f50c14..ddab85ec 100644 --- a/lib/common/widgets/time_picker.dart +++ b/lib/common/widgets/time_picker.dart @@ -18,6 +18,7 @@ import 'package:clock_app/theme/border.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; // Examples can assume: // late BuildContext context; @@ -304,21 +305,21 @@ class _TitleBar extends StatelessWidget { onPickerModeChanged(); }, title: setting.name, - description: setting.description, - choices: setting.options + description: setting.displayDescription(context), + getChoices: () => setting.options .map((option) => SelectChoice( - name: option.name, + name: option.getLocalizedName(context), value: option.value, - description: option.description)) + description: option.getDescription(context))) .toList(), - initialSelectedIndices: [setting.selectedIndex], + getCurrentSelectedIndices: () => [setting.selectedIndex], multiSelect: false, ); appSettings.save(); }, child: Text( - "Mode", + AppLocalizations.of(context)!.timePickerModeButton, style: Theme.of(context).textTheme.titleSmall?.copyWith( color: Theme.of(context).colorScheme.primary, ), @@ -1449,6 +1450,7 @@ class _TimePickerInput extends StatefulWidget { required this.autofocusHour, required this.autofocusMinute, required this.onChanged, + required this.use24hFormat, this.restorationId, // required this.entryMode, // required this.handleEntryModeToggle, @@ -1480,6 +1482,8 @@ class _TimePickerInput extends StatefulWidget { final ValueChanged onChanged; + final bool use24hFormat; + /// Restoration ID to save and restore the state of the time picker input /// widget. /// @@ -1612,7 +1616,7 @@ class _TimePickerInputState extends State<_TimePickerInput> final MediaQueryData media = MediaQuery.of(context); final TimeOfDayFormat timeOfDayFormat = MaterialLocalizations.of(context) .timeOfDayFormat(alwaysUse24HourFormat: media.alwaysUse24HourFormat); - final bool use24HourDials = hourFormat(of: timeOfDayFormat) != HourFormat.h; + // final bool use24HourDials = hourFormat(of: timeOfDayFormat) != HourFormat.h; final ThemeData theme = Theme.of(context); final TextStyle hourMinuteStyle = TimePickerTheme.of(context).hourMinuteTextStyle ?? @@ -1634,7 +1638,7 @@ class _TimePickerInputState extends State<_TimePickerInput> child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (!use24HourDials && + if (!widget.use24hFormat && timeOfDayFormat == TimeOfDayFormat.a_space_h_colon_mm) ...[ _DayPeriodControl( @@ -1718,7 +1722,7 @@ class _TimePickerInputState extends State<_TimePickerInput> ], ), ), - if (!use24HourDials && + if (!widget.use24hFormat && timeOfDayFormat != TimeOfDayFormat.a_space_h_colon_mm) ...[ const SizedBox(width: 12.0), @@ -2381,7 +2385,7 @@ class _TimePickerDialogState extends State final MediaQueryData media = MediaQuery.of(context); final TimeOfDayFormat timeOfDayFormat = localizations.timeOfDayFormat( alwaysUse24HourFormat: media.alwaysUse24HourFormat); - final bool use24HourDials = hourFormat(of: timeOfDayFormat) != HourFormat.h; + // final bool use24HourDials = hourFormat(of: timeOfDayFormat) != HourFormat.h; final ThemeData theme = Theme.of(context); final ShapeBorder shape = TimePickerTheme.of(context).shape ?? _kDefaultShape; @@ -2401,7 +2405,7 @@ class _TimePickerDialogState extends State ), onPressed: _handleCancel, child: Text( - "Cancel", + AppLocalizations.of(context)!.cancelButton, style: Theme.of(context).textTheme.labelMedium?.copyWith( color: Theme.of(context) .colorScheme @@ -2422,7 +2426,7 @@ class _TimePickerDialogState extends State TextButton( onPressed: () => _handleOk(type, isCustomize: true), child: Text( - "Customize", + AppLocalizations.of(context)!.customizeButton, style: Theme.of(context).textTheme.labelMedium?.copyWith( color: Theme.of(context).colorScheme.primary), ), @@ -2444,113 +2448,13 @@ class _TimePickerDialogState extends State final Size dialogSize = _dialogSize(context, type); final Widget picker; - // switch (_entryMode.value) { - // case TimePickerEntryMode.dial: - // case TimePickerEntryMode.dialOnly: - // final Widget dial = Padding( - // padding: orientation == Orientation.portrait - // ? const EdgeInsets.symmetric(horizontal: 24, vertical: 16) - // : const EdgeInsets.only(right: 12, left: 12, top: 24, bottom: 12), - // child: ExcludeSemantics( - // child: AspectRatio( - // aspectRatio: 1.0, - // child: _Dial( - // mode: _mode.value, - // use24HourDials: use24HourDials, - // selectedTime: _selectedTime.value, - // onChanged: _handleTimeChanged, - // onHourSelected: _handleHourSelected, - // ), - // ), - // ), - // ); - // - // final Widget header = _TimePickerHeader( - // selectedTime: _selectedTime.value, - // mode: _mode.value, - // orientation: orientation, - // onModeChanged: _handleModeChanged, - // onChanged: _handleTimeChanged, - // onHourDoubleTapped: _handleHourDoubleTapped, - // onMinuteDoubleTapped: _handleMinuteDoubleTapped, - // use24HourDials: use24HourDials, - // helpText: widget.title, - // entryMode: _entryMode, - // handleEntryModeToggle: _handleEntryModeToggle, - // ); - // - // switch (orientation) { - // case Orientation.portrait: - // picker = Column( - // mainAxisSize: MainAxisSize.min, - // crossAxisAlignment: CrossAxisAlignment.stretch, - // children: [ - // // header, - // Expanded( - // child: Column( - // mainAxisSize: MainAxisSize.min, - // children: [ - // // Dial grows and shrinks with the available space. - // Expanded(child: dial), - // actions, - // ], - // ), - // ), - // ], - // ); - // break; - // case Orientation.landscape: - // picker = Column( - // children: [ - // Expanded( - // child: Row( - // children: [ - // // header, - // Expanded(child: dial), - // ], - // ), - // ), - // actions, - // ], - // ); - // break; - // } - // break; - // case TimePickerEntryMode.input: - // case TimePickerEntryMode.inputOnly: - // picker = Form( - // key: _formKey, - // autovalidateMode: _autovalidateMode.value, - // child: SingleChildScrollView( - // restorationId: 'time_picker_scroll_view', - // child: Column( - // mainAxisSize: MainAxisSize.min, - // children: [ - // - // _TimePickerInput( - // initialSelectedTime: _selectedTime.value, - // helpText: widget.title, - // errorInvalidText: widget.errorInvalidText, - // hourLabelText: widget.hourLabelText, - // minuteLabelText: widget.minuteLabelText, - // autofocusHour: _autofocusHour.value, - // autofocusMinute: _autofocusMinute.value, - // onChanged: _handleTimeChanged, - // restorationId: 'time_picker_input', - // entryMode: _entryMode, - // handleEntryModeToggle: _handleEntryModeToggle, - // ), - // actions, - // ], - // ), - // ), - // ); - // break; - // } -// ThemeData theme = Theme.of(context); - TextTheme textTheme = theme.textTheme; + TextTheme textTheme = theme.textTheme; ColorScheme colorScheme = theme.colorScheme; + bool use24hMode = MediaQuery.of(context).alwaysUse24HourFormat || + appSettings.getSetting("Time Format").value == + TimeFormat.h24; + switch (type) { case TimePickerType.spinner: picker = SizedBox( @@ -2566,9 +2470,7 @@ class _TimePickerDialogState extends State padding: const EdgeInsets.symmetric(horizontal: 24.0), child: TimePickerSpinner( time: _selectedTime.value.toDateTime(), - is24HourMode: MediaQuery.of(context).alwaysUse24HourFormat || - appSettings.getSetting("Time Format").value == - TimeFormat.h24, + is24HourMode: use24hMode, normalTextStyle: orientation == Orientation.portrait ? textTheme.displayMedium?.copyWith( color: colorScheme.onSurface.withOpacity(0.5)) @@ -2604,7 +2506,7 @@ class _TimePickerDialogState extends State onChanged: _handleTimeChanged, onHourDoubleTapped: () => _handleHourDoubleTapped(type), onMinuteDoubleTapped: () => _handleMinuteDoubleTapped(type), - use24HourDials: use24HourDials, + use24HourDials: use24hMode, helpText: widget.title, // entryMode: _entryMode, handlePickerModeChange: _handlePickerTypeChange, @@ -2630,7 +2532,7 @@ class _TimePickerDialogState extends State aspectRatio: 1.0, child: _Dial( mode: _mode.value, - use24HourDials: use24HourDials, + use24HourDials: use24hMode, selectedTime: _selectedTime.value, onChanged: _handleTimeChanged, onHourSelected: _handleHourSelected, @@ -2657,6 +2559,7 @@ class _TimePickerDialogState extends State autofocusMinute: _autofocusMinute.value, onChanged: _handleTimeChanged, restorationId: 'time_picker_input', + use24hFormat: use24hMode, // entryMode: _entryMode, // handleEntryModeToggle: _handleEntryModeToggle, onModeChanged: _handlePickerTypeChange, diff --git a/lib/l10n/app_bn.arb b/lib/l10n/app_bn.arb new file mode 100644 index 00000000..122bfb0c --- /dev/null +++ b/lib/l10n/app_bn.arb @@ -0,0 +1,124 @@ +{ + "pickerRings": "রিং", + "@pickerRings": {}, + "pickerDial": "ডায়াল", + "@pickerDial": {}, + "swipeActionCardActionDescription": "কাজ সম্পাদন করতে কার্ডের বাম বা ডানদিকে সোয়াইপ করুন", + "@swipeActionCardActionDescription": {}, + "vendorSettingDescription": "ম্যানুয়ালি কোম্পানি-নির্দিষ্ট সীমাবদ্ধতা বন্ধ করুন", + "@vendorSettingDescription": {}, + "batteryOptimizationSettingDescription": "অ্যালার্ম দেরি হওয়া থেকে আটকাতে এই অ্যাপের জন্য ব্যাটারি সীমাবদ্ধতা বন্ধ করুন", + "@batteryOptimizationSettingDescription": {}, + "animationSettingGroup": "অ্যানিমেশন", + "@animationSettingGroup": {}, + "animationSpeedSetting": "অ্যানিমেশনের গতি", + "@animationSpeedSetting": {}, + "autoStartSetting": "অটোমেটিক শুরু", + "@autoStartSetting": {}, + "colorSchemeUseAccentAsOutlineSetting": "আউটলাইনের রঙ হিসাবে পরিপূরক রঙ ব্যবহার করুন", + "@colorSchemeUseAccentAsOutlineSetting": {}, + "styleThemeNamePlaceholder": "স্টাইল থিম", + "@styleThemeNamePlaceholder": {}, + "timerTitle": "টাইমার", + "@timerTitle": { + "description": "Title of the timer screen" + }, + "stopwatchTitle": "স্টপওয়াচ", + "@stopwatchTitle": { + "description": "Title of the stopwatch screen" + }, + "system": "পদ্ধতি", + "@system": {}, + "generalSettingGroup": "সাধারণ", + "@generalSettingGroup": {}, + "dateFormatSetting": "তারিখ বিন্যাস", + "@dateFormatSetting": {}, + "generalSettingGroupDescription": "সময় বিন্যাসের মতো অ্যাপ ওয়াইড সেটিংস সেট করুন", + "@generalSettingGroupDescription": {}, + "timeFormatSetting": "সময়ের বিন্যাস", + "@timeFormatSetting": {}, + "timeFormat12": "১২ ঘণ্টা", + "@timeFormat12": {}, + "timeFormat24": "২৪ ঘন্টা", + "@timeFormat24": {}, + "timeFormatDevice": "ডিভাইস সেটিংস", + "@timeFormatDevice": {}, + "showSecondsSetting": "সেকেন্ড দেখান", + "@showSecondsSetting": {}, + "timePickerSetting": "সময় বাছাইকারী", + "@timePickerSetting": {}, + "pickerInput": "নির্দেশ", + "@pickerInput": {}, + "pickerSpinner": "ঘূর্ণন", + "@pickerSpinner": {}, + "durationPickerSetting": "সময়কাল বাছাইকারী", + "@durationPickerSetting": {}, + "swipeActionSetting": "সোয়াইপ করুন", + "@swipeActionSetting": {}, + "swipActionCardAction": "কার্ড কর্ম", + "@swipActionCardAction": {}, + "swipActionSwitchTabs": "ট্যাব পরিবর্তন করুন", + "@swipActionSwitchTabs": {}, + "swipeActionSwitchTabsDescription": "ট্যাবের মধ্যে সোয়াইপ করুন", + "@swipeActionSwitchTabsDescription": {}, + "melodiesSetting": "শব্দ", + "@melodiesSetting": {}, + "tagsSetting": "চিহ্ন", + "@tagsSetting": {}, + "vendorSetting": "কোম্পানির সেটিং", + "@vendorSetting": {}, + "batteryOptimizationSetting": "ব্যাটারি সীমাবদ্ধতা বন্ধ করুন", + "@batteryOptimizationSetting": {}, + "allowNotificationSettingDescription": "অ্যালার্ম এবং টাইমারগুলির জন্য লক স্ক্রীন নোটিফিকেশন অনুমতি দিন", + "@allowNotificationSettingDescription": {}, + "autoStartSettingDescription": "অ্যাপ বন্ধ থাকা অবস্থায় অ্যালার্ম বাজানোর জন্য কিছু ডিভাইসে অটোমেটিক শুরু হওয়া করা প্রয়োজন", + "@autoStartSettingDescription": {}, + "allowNotificationSetting": "নোটিফিকেশন অনুমতি দিন", + "@allowNotificationSetting": {}, + "extraAnimationSetting": "অতিরিক্ত অ্যানিমেশন", + "@extraAnimationSetting": {}, + "appearanceSettingGroup": "উপস্থিতি", + "@appearanceSettingGroup": {}, + "appearanceSettingGroupDescription": "থিম, রং সেট করুন এবং লেআউট পরিবর্তন করুন", + "@appearanceSettingGroupDescription": {}, + "nameField": "নাম", + "@nameField": {}, + "colorSetting": "রঙ", + "@colorSetting": {}, + "textColorSetting": "লেখা", + "@textColorSetting": {}, + "colorSchemeNamePlaceholder": "রঙের পরিকল্পনা", + "@colorSchemeNamePlaceholder": {}, + "colorSchemeBackgroundSettingGroup": "ব্যাকগ্রাউন্ড", + "@colorSchemeBackgroundSettingGroup": {}, + "colorSchemeAccentSettingGroup": "পরিপূরক রঙ", + "@colorSchemeAccentSettingGroup": {}, + "colorSchemeErrorSettingGroup": "ত্রুটি", + "@colorSchemeErrorSettingGroup": {}, + "colorSchemeCardSettingGroup": "কার্ড", + "@colorSchemeCardSettingGroup": {}, + "colorSchemeShadowSettingGroup": "ছায়া", + "@colorSchemeShadowSettingGroup": {}, + "colorSchemeOutlineSettingGroup": "আউটলাইন", + "@colorSchemeOutlineSettingGroup": {}, + "colorSchemeUseAccentAsShadowSetting": "ছায়া হিসাবে পরিপূরক রঙ ব্যবহার করুন", + "@colorSchemeUseAccentAsShadowSetting": {}, + "styleThemeShadowSettingGroup": "ছায়া", + "@styleThemeShadowSettingGroup": {}, + "styleThemeShapeSettingGroup": "আকৃতি", + "@styleThemeShapeSettingGroup": {}, + "styleThemeElevationSetting": "উচ্চতা", + "@styleThemeElevationSetting": {}, + "styleThemeRadiusSetting": "কোণার গোলাকারতা", + "@styleThemeRadiusSetting": {}, + "clockTitle": "ঘড়ি", + "@clockTitle": { + "description": "Title of the clock screen" + }, + "alarmTitle": "এলার্ম", + "@alarmTitle": { + "description": "Title of the alarm screen" + }, + "languageSetting": "ভাষা", + "@languageSetting": {} +} diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb new file mode 100644 index 00000000..39e83eeb --- /dev/null +++ b/lib/l10n/app_de.arb @@ -0,0 +1,176 @@ +{ + "reliabilitySettingGroup": "Zuverlässigkeit", + "@reliabilitySettingGroup": {}, + "developerOptionsSettingGroup": "Entwickleroptionen", + "@developerOptionsSettingGroup": {}, + "colorsSettingGroup": "Farben", + "@colorsSettingGroup": {}, + "overrideAccentSetting": "Akzentfarbe überschreiben", + "@overrideAccentSetting": {}, + "appearanceSettingGroupDescription": "Setze Themes, Farben und ändere das Layout", + "@appearanceSettingGroupDescription": {}, + "scheduleTypeDateDescription": "Wird an den angegebenen Tagen wiederholt", + "@scheduleTypeDateDescription": {}, + "scheduleTypeRangeDescription": "Wird während des angegebenen Datumsbereichs wiederholt", + "@scheduleTypeRangeDescription": {}, + "melodySetting": "Melodie", + "@melodySetting": {}, + "whileSnoozedSettingGroup": "Während Schlummern", + "@whileSnoozedSettingGroup": {}, + "tasksSetting": "Aufgaben", + "@tasksSetting": {}, + "noItemMessage": "Noch keine {items} hinzugefügt", + "@noItemMessage": {}, + "chooseTaskTitle": "Aufgabe auswählen", + "@chooseTaskTitle": {}, + "mathTask": "Matheaufgaben", + "@mathTask": {}, + "taskTryButton": "Ausprobieren", + "@taskTryButton": {}, + "retypeTask": "Text neu eingeben", + "@retypeTask": {}, + "sequenceTask": "Sequenz", + "@sequenceTask": {}, + "clockTitle": "Uhr", + "@clockTitle": { + "description": "Title of the clock screen" + }, + "alarmTitle": "Wecker", + "@alarmTitle": { + "description": "Title of the alarm screen" + }, + "timerTitle": "Timer", + "@timerTitle": { + "description": "Title of the timer screen" + }, + "stopwatchTitle": "Stoppuhr", + "@stopwatchTitle": { + "description": "Title of the stopwatch screen" + }, + "generalSettingGroup": "Allgemein", + "@generalSettingGroup": {}, + "accessibilitySettingGroup": "Barrierefreiheit", + "@accessibilitySettingGroup": {}, + "backupSettingGroup": "Sicherung", + "@backupSettingGroup": {}, + "aboutSettingGroup": "Über", + "@aboutSettingGroup": {}, + "restoreSettingGroup": "Einstellungen zurücksetzten", + "@restoreSettingGroup": {}, + "appearanceSettingGroup": "Darstellung", + "@appearanceSettingGroup": {}, + "displaySettingGroup": "Darstellung", + "@displaySettingGroup": {}, + "styleSettingGroup": "Design", + "@styleSettingGroup": {}, + "useMaterialYouColorSetting": "Nutze Material You", + "@useMaterialYouColorSetting": {}, + "materialBrightnessSetting": "Helligkeit", + "@materialBrightnessSetting": {}, + "useMaterialStyleSetting": "Nutze Material Design", + "@useMaterialStyleSetting": {}, + "systemDarkModeSetting": "System-Dunkelmodus", + "@systemDarkModeSetting": {}, + "colorSchemeSetting": "Farbschema", + "@colorSchemeSetting": {}, + "darkColorSchemeSetting": "Dunkles Farbschema", + "@darkColorSchemeSetting": {}, + "clockSettingGroup": "Uhr", + "@clockSettingGroup": {}, + "timerSettingGroup": "Timer", + "@timerSettingGroup": {}, + "stopwatchSettingGroup": "Stoppuhr", + "@stopwatchSettingGroup": {}, + "generalSettingGroupDescription": "Setze App-weite Einstellungen wie das Zeitformat", + "@generalSettingGroupDescription": {}, + "backupSettingGroupDescription": "Exportiere oder importiere deine Einstellungen lokal", + "@backupSettingGroupDescription": {}, + "selectTime": "Zeit auswählen", + "@selectTime": {}, + "cancelButton": "Abbrechen", + "@cancelButton": {}, + "customizeButton": "Anpassen", + "@customizeButton": {}, + "saveButton": "Speichern Button", + "@saveButton": {}, + "labelField": "Bezeichnung", + "@labelField": {}, + "labelFieldPlaceholder": "Füge eine Bezeichnung hinzu", + "@labelFieldPlaceholder": {}, + "scheduleTypeField": "Typ", + "@scheduleTypeField": {}, + "scheduleTypeOnce": "Einmal", + "@scheduleTypeOnce": {}, + "alarmScheduleSettingGroup": "Zeitplan", + "@alarmScheduleSettingGroup": {}, + "scheduleTypeDaily": "Täglich", + "@scheduleTypeDaily": {}, + "scheduleTypeOnceDescription": "Wird beim nächsten Auftreten der Zeit klingeln", + "@scheduleTypeOnceDescription": {}, + "scheduleTypeDailyDescription": "Wird jeden Tag klingeln", + "@scheduleTypeDailyDescription": {}, + "scheduleTypeWeek": "An bestimmten Wochentagen", + "@scheduleTypeWeek": {}, + "scheduleTypeWeekDescription": "Wird an den bestimmten Wochentagen wiederholt", + "@scheduleTypeWeekDescription": {}, + "scheduleTypeRange": "Datumsbereich", + "@scheduleTypeRange": {}, + "settingGroupMore": "Mehr", + "@settingGroupMore": {}, + "soundSettingGroup": "Ton und Vibration", + "@soundSettingGroup": {}, + "vibrationSetting": "Vibration", + "@vibrationSetting": {}, + "audioChannelSetting": "Audio-Kanal", + "@audioChannelSetting": {}, + "volumeSetting": "Lautstärke", + "@volumeSetting": {}, + "risingVolumeSetting": "Ansteigende Lautstärke", + "@risingVolumeSetting": {}, + "snoozeSettingGroup": "Schlummern", + "@snoozeSettingGroup": {}, + "snoozeEnableSetting": "Aktiviert", + "@snoozeEnableSetting": {}, + "snoozeLengthSetting": "Dauer", + "@snoozeLengthSetting": {}, + "settings": "Einstellungen", + "@settings": {}, + "mathTaskDifficultySetting": "Schwierigkeit", + "@mathTaskDifficultySetting": {}, + "skippingDescriptionSuffix": "(Nächstes Mal überspringen)", + "@skippingDescriptionSuffix": {}, + "alarmDescriptionSnooze": "Schlummern bis {date}", + "@alarmDescriptionSnooze": {}, + "alarmDescriptionFinished": "Keine zukünftigen Tagen", + "@alarmDescriptionFinished": {}, + "alarmDescriptionNotScheduled": "Nicht geplant", + "@alarmDescriptionNotScheduled": {}, + "alarmDescriptionToday": "Nur heute", + "@alarmDescriptionToday": {}, + "alarmDescriptionTomorrow": "Nur morgen", + "@alarmDescriptionTomorrow": {}, + "alarmDescriptionEveryDay": "Jeden Tag", + "@alarmDescriptionEveryDay": {}, + "alarmDescriptionWeekend": "Jedes Wochenende", + "@alarmDescriptionWeekend": {}, + "stopwatchPrevious": "Vorherige", + "@stopwatchPrevious": {}, + "alarmDescriptionWeekday": "Jeden Wochentag", + "@alarmDescriptionWeekday": {}, + "stopwatchFastest": "Schnellste", + "@stopwatchFastest": {}, + "alarmDescriptionDays": "An {days}", + "@alarmDescriptionDays": {}, + "alarmDescriptionRange": "{interval, select, daily{Täglich} weekly{Wöchentlich} other{Other}} von {startDate} bis {endDate}", + "@alarmDescriptionRange": {}, + "stopwatchSlowest": "Langsamste", + "@stopwatchSlowest": {}, + "alarmDescriptionDates": "Am {date}{count, plural, =0{} =1{ and 1 other date} other{ und {count} anderen Daten}}", + "@alarmDescriptionDates": {}, + "stopwatchAverage": "Durchschnitt", + "@stopwatchAverage": {}, + "styleThemeSetting": "Designauswahl", + "@styleThemeSetting": {}, + "snoozePreventDisablingSetting": "Deaktivierung verhindern", + "@snoozePreventDisablingSetting": {} +} diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb new file mode 100644 index 00000000..8cb0ceef --- /dev/null +++ b/lib/l10n/app_en.arb @@ -0,0 +1,626 @@ +{ + "clockTitle": "Clock", + "@clockTitle": { + "description": "Title of the clock screen" + }, + "alarmTitle": "Alarm", + "@alarmTitle": { + "description": "Title of the alarm screen" + }, + "timerTitle": "Timer", + "@timerTitle": { + "description": "Title of the timer screen" + }, + "stopwatchTitle": "Stopwatch", + "@stopwatchTitle": { + "description": "Title of the stopwatch screen" + }, + "system": "System", + "@system": {}, + "generalSettingGroup": "General", + "@generalSettingGroup": {}, + "generalSettingGroupDescription": "Set app wide settings like time format", + "@generalSettingGroupDescription": {}, + "languageSetting": "Language", + "@languageSetting": {}, + "dateFormatSetting": "Date Format", + "@dateFormatSetting": {}, + "timeFormatSetting": "Time Format", + "@timeFormatSetting": {}, + "timeFormat12": "12 hours", + "@timeFormat12": {}, + "timeFormat24": "24 hours", + "@timeFormat24": {}, + "timeFormatDevice": "Device Settings", + "@timeFormatDevice": {}, + "showSecondsSetting": "Show Seconds", + "@showSecondsSetting": {}, + "timePickerSetting": "Time Picker", + "@timePickerSetting": {}, + "pickerDial": "Dial", + "@pickerDial": {}, + "pickerInput": "Input", + "@pickerInput": {}, + "pickerSpinner": "Spinner", + "@pickerSpinner": {}, + "durationPickerSetting": "Duration Picker", + "@durationPickerSetting": {}, + "pickerRings": "Rings", + "@pickerRings": {}, + "swipeActionSetting": "Swipe Action", + "@swipeActionSetting": {}, + "swipActionCardAction": "Card Actions", + "@swipActionCardAction": {}, + "swipeActionCardActionDescription": "Swipe left or right on the card to perform actions", + "@swipeActionCardActionDescription": {}, + "swipActionSwitchTabs": "Switch Tabs", + "@swipActionSwitchTabs": {}, + "swipeActionSwitchTabsDescription": "Swipe between tabs", + "@swipeActionSwitchTabsDescription": {}, + "melodiesSetting": "Melodies", + "@melodiesSetting": {}, + "tagsSetting": "Tags", + "@tagsSetting": {}, + "vendorSetting": "Vendor Settings", + "@vendorSetting": {}, + "vendorSettingDescription": "Manually disable vendor-specific optimizations", + "@vendorSettingDescription": {}, + "batteryOptimizationSetting": "Disable Battery Optimization", + "@batteryOptimizationSetting": {}, + "batteryOptimizationSettingDescription": "Disable battery optimization for this app to prevent alarms from being delayed", + "@batteryOptimizationSettingDescription": {}, + "allowNotificationSettingDescription": "Allow lock screen notifications for alarms and timers", + "@allowNotificationSettingDescription": {}, + "autoStartSettingDescription": "Some devices require Auto Start to be enabled for alarms to ring while app is closed", + "@autoStartSettingDescription": {}, + "allowNotificationSetting": "Allow Notifications", + "@allowNotificationSetting": {}, + "autoStartSetting": "Auto Start", + "@autoStartSetting": {}, + "animationSettingGroup": "Animations", + "@animationSettingGroup": {}, + "animationSpeedSetting": "Animation Speed", + "@animationSpeedSetting": {}, + "extraAnimationSetting": "Extra Animations", + "@extraAnimationSetting": {}, + "appearanceSettingGroup": "Appearance", + "@appearanceSettingGroup": {}, + "appearanceSettingGroupDescription": "Set themes, colors and change layout", + "@appearanceSettingGroupDescription": {}, + "nameField": "Name", + "@nameField": {}, + "colorSetting": "Color", + "@colorSetting": {}, + "textColorSetting": "Text", + "@textColorSetting": {}, + "colorSchemeNamePlaceholder": "Color Scheme", + "@colorSchemeNamePlaceholder": {}, + "colorSchemeBackgroundSettingGroup": "Background", + "@colorSchemeBackgroundSettingGroup": {}, + "colorSchemeAccentSettingGroup": "Accent", + "@colorSchemeAccentSettingGroup": {}, + "colorSchemeErrorSettingGroup": "Error", + "@colorSchemeErrorSettingGroup": {}, + "colorSchemeCardSettingGroup": "Card", + "@colorSchemeCardSettingGroup": {}, + "colorSchemeOutlineSettingGroup": "Outline", + "@colorSchemeOutlineSettingGroup": {}, + "colorSchemeShadowSettingGroup": "Shadow", + "@colorSchemeShadowSettingGroup": {}, + "colorSchemeUseAccentAsOutlineSetting": "Use Accent as Outline", + "@colorSchemeUseAccentAsOutlineSetting": {}, + "colorSchemeUseAccentAsShadowSetting": "Use Accent as Shadow", + "@colorSchemeUseAccentAsShadowSetting": {}, + "styleThemeNamePlaceholder": "Style Theme", + "@styleThemeNamePlaceholder": {}, + "styleThemeShadowSettingGroup": "Shadow", + "@styleThemeShadowSettingGroup": {}, + "styleThemeShapeSettingGroup": "Shape", + "@styleThemeShapeSettingGroup": {}, + "styleThemeElevationSetting": "Elevation", + "@styleThemeElevationSetting": {}, + "styleThemeRadiusSetting": "Corner Roundness", + "@styleThemeRadiusSetting": {}, + "styleThemeOpacitySetting": "Opacity", + "@styleThemeOpacitySetting": {}, + "styleThemeBlurSetting": "Blur", + "@styleThemeBlurSetting": {}, + "styleThemeSpreadSetting": "Spread", + "@styleThemeSpreadSetting": {}, + "styleThemeOutlineSettingGroup": "Outline", + "@styleThemeOutlineSettingGroup": {}, + "styleThemeOutlineWidthSetting": "Width", + "@styleThemeOutlineWidthSetting": {}, + "accessibilitySettingGroup": "Accessibility", + "@accessibilitySettingGroup": {}, + "backupSettingGroup": "Settings", + "@backupSettingGroup": {}, + "developerOptionsSettingGroup": "Developer Options", + "@developerOptionsSettingGroup": {}, + "showIstantAlarmButtonSetting": "Show Instant Alarm Button", + "@showIstantAlarmButtonSetting": {}, + "showIstantTimerButtonSetting": "Show Instant Timer Button", + "@showIstantTimerButtonSetting": {}, + "logsSettingGroup": "Logs", + "@logsSettingGroup": {}, + "maxLogsSetting": "Max Logs", + "@maxLogsSetting": {}, + "alarmLogSetting": "Alarm Logs", + "@alarmLogSetting": {}, + "aboutSettingGroup": "About", + "@aboutSettingGroup": {}, + "restoreSettingGroup": "Restore default values", + "@restoreSettingGroup": {}, + "resetButton": "Reset", + "@resetButton": {}, + "previewLabel": "Preview", + "@previewLabel": {}, + "cardLabel": "Card", + "@cardLabel": {}, + "accentLabel": "Accent", + "@accentLabel": {}, + "errorLabel": "Error", + "@errorLabel": {}, + "displaySettingGroup": "Display", + "@displaySettingGroup": {}, + "reliabilitySettingGroup": "Reliability", + "@reliabilitySettingGroup": {}, + "colorsSettingGroup": "Colors", + "@colorsSettingGroup": {}, + "styleSettingGroup": "Style", + "@styleSettingGroup": {}, + "useMaterialYouColorSetting": "Use Material You", + "@useMaterialYouColorSetting": {}, + "materialBrightnessSetting": "Brightness", + "@materialBrightnessSetting": {}, + "materialBrightnessSystem": "System", + "@materialBrightnessSystem": {}, + "materialBrightnessLight": "Light", + "@materialBrightnessLight": {}, + "materialBrightnessDark": "Dark", + "@materialBrightnessDark": {}, + "overrideAccentSetting": "Override Accent Color", + "@overrideAccentSetting": {}, + "accentColorSetting": "Accent Color", + "@accentColorSetting": {}, + "useMaterialStyleSetting": "Use Material Style", + "@useMaterialStyleSetting": {}, + "styleThemeSetting": "Style Theme", + "@styleThemeSetting": {}, + "systemDarkModeSetting": "System Dark Mode", + "@systemDarkModeSetting": {}, + "colorSchemeSetting": "Color Scheme", + "@colorSchemeSetting": {}, + "darkColorSchemeSetting": "Dark Color Scheme", + "@darkColorSchemeSetting": {}, + "clockSettingGroup": "Clock", + "@clockSettingGroup": {}, + "timerSettingGroup": "Timer", + "@timerSettingGroup": {}, + "stopwatchSettingGroup": "Stopwatch", + "@stopwatchSettingGroup": {}, + "backupSettingGroupDescription": "Export or Import your settings locally", + "@backupSettingGroupDescription": {}, + "alarmWeekdaysSetting": "Week Days", + "@alarmWeekdaysSetting": {}, + "alarmDatesSetting": "Dates", + "@alarmDatesSetting": {}, + "alarmRangeSetting": "Date Range", + "@alarmRangeSetting": {}, + "alarmIntervalSetting": "Interval", + "@alarmIntervalSetting": {}, + "alarmIntervalDaily": "Daily", + "@alarmIntervalDaily": {}, + "alarmIntervalWeekly": "Weekly", + "@alarmIntervalWeekly": {}, + "alarmDeleteAfterRingingSetting": "Delete After Dismiss", + "@alarmDeleteAfterRingingSetting": {}, + "alarmDeleteAfterFinishingSetting": "Delete After Finishing", + "@alarmDeleteAfterFinishingSetting": {}, + "cannotDisableAlarmWhileSnoozedSnackbar": "Cannot disable alarm while it is snoozed", + "@cannotDisableAlarmWhileSnoozedSnackbar": {}, + "selectTime": "Select Time", + "@selectTime": {}, + "timePickerModeButton": "Mode", + "@timePickerModeButton": {}, + "cancelButton": "Cancel", + "@cancelButton": {}, + "customizeButton": "Customize", + "@customizeButton": {}, + "saveButton": "Save", + "@saveButton": {}, + "labelField": "Label", + "@labelField": {}, + "labelFieldPlaceholder": "Add a label", + "@labelFieldPlaceholder": {}, + "alarmScheduleSettingGroup": "Schedule", + "@alarmScheduleSettingGroup": {}, + "scheduleTypeField": "Type", + "@scheduleTypeField": {}, + "scheduleTypeOnce": "Once", + "@scheduleTypeOnce": {}, + "scheduleTypeDaily": "Daily", + "@scheduleTypeDaily": {}, + "scheduleTypeOnceDescription": "Will ring at the next occurrence of the time", + "@scheduleTypeOnceDescription": {}, + "scheduleTypeDailyDescription": "Will ring every day", + "@scheduleTypeDailyDescription": {}, + "scheduleTypeWeek": "On Specified Week Days", + "@scheduleTypeWeek": {}, + "scheduleTypeWeekDescription": "Will repeat on the specified week days", + "@scheduleTypeWeekDescription": {}, + "scheduleTypeDate": "On Specific Dates", + "@scheduleTypeDate": {}, + "scheduleTypeRange": "Date Range", + "@scheduleTypeRange": {}, + "scheduleTypeDateDescription": "Will repeat on the specified dates", + "@scheduleTypeDateDescription": {}, + "scheduleTypeRangeDescription": "Will repeat during the specified date range", + "@scheduleTypeRangeDescription": {}, + "soundAndVibrationSettingGroup": "Sound and Vibration", + "@soundAndVibrationSettingGroup": {}, + "soundSettingGroup": "Sound", + "@soundSettingGroup": {}, + "settingGroupMore": "More", + "@settingGroupMore": {}, + "melodySetting": "Melody", + "@melodySetting": {}, + "vibrationSetting": "Vibration", + "@vibrationSetting": {}, + "audioChannelSetting": "Audio Channel", + "@audioChannelSetting": {}, + "audioChannelAlarm": "Alarm", + "@audioChannelAlarm": {}, + "audioChannelNotification": "Notification", + "@audioChannelNotification": {}, + "audioChannelRingtone": "Ringtone", + "@audioChannelRingtone": {}, + "audioChannelMedia": "Media", + "@audioChannelMedia": {}, + "volumeSetting": "Volume", + "@volumeSetting": {}, + "risingVolumeSetting": "Rising Volume", + "@risingVolumeSetting": {}, + "timeToFullVolumeSetting": "Time to Full Volume", + "@timeToFullVolumeSetting": {}, + "snoozeSettingGroup": "Snooze", + "@snoozeSettingGroup": {}, + "snoozeEnableSetting": "Enabled", + "@snoozeEnableSetting": {}, + "snoozeLengthSetting": "Length", + "@snoozeLengthSetting": {}, + "maxSnoozesSetting": "Max Snoozes", + "@maxSnoozesSetting": {}, + "whileSnoozedSettingGroup": "While Snoozed", + "@whileSnoozedSettingGroup": {}, + "snoozePreventDisablingSetting": "Prevent Disabling", + "@snoozePreventDisablingSetting": {}, + "snoozePreventDeletionSetting": "Prevent Deletion", + "@snoozePreventDeletionSetting": {}, + "settings": "Settings", + "@settings": {}, + "tasksSetting": "Tasks", + "@tasksSetting": {}, + "noItemMessage": "No {items} added yet", + "@noItemMessage": {}, + "chooseTaskTitle": "Choose Task to Add", + "@chooseTaskTitle": {}, + "mathTask": "Math Problems", + "@mathTask": {}, + "mathEasyDifficulty": "Easy (X + Y)", + "@mathEasyDifficulty": {}, + "mathMediumDifficulty": "Medium (X × Y)", + "@mathMediumDifficulty": {}, + "mathHardDifficulty": "Hard (X × Y + Z)", + "@mathHardDifficulty": {}, + "mathVeryHardDifficulty": "Very Hard (X × Y × Z)", + "@mathVeryHardDifficulty": {}, + "retypeTask": "Retype Text", + "@retypeTask": {}, + "sequenceTask": "Sequence", + "@sequenceTask": {}, + "taskTryButton": "Try Out", + "@taskTryButton": {}, + "mathTaskDifficultySetting": "Difficulty", + "@mathTaskDifficultySetting": {}, + "retypeNumberChars": "Number of characters", + "@retypeNumberChars": {}, + "retypeIncludeNumSetting": "Include numbers", + "@retypeIncludeNumSetting": {}, + "retypeLowercaseSetting": "Include lowercase", + "@retypeLowercaseSetting": {}, + "sequenceLengthSetting": "Sequence length", + "@sequenceLengthSetting": {}, + "sequenceGridSizeSetting": "Grid size", + "@sequenceGridSizeSetting": {}, + "numberOfProblemsSetting": "Number of Problems", + "@numberOfProblemsSetting": {}, + "saveReminderAlert": "Do you want to leave without saving?", + "@saveReminderAlert": {}, + "yesButton": "Yes", + "@yesButton": {}, + "noButton": "No", + "@noButton": {}, + "noAlarmMessage": "No alarms created", + "@noAlarmMessage": {}, + "noTimerMessage": "No timers created", + "@noTimerMessage": {}, + "noStopwatchMessage": "No stopwatches created", + "@noStopwatchMessage": {}, + "noTaskMessage": "No tasks created", + "@noTaskMessage": {}, + "noPresetsMessage": "No presets created", + "@noPresetsMessage": {}, + "noLogsMessage": "No alarm logs", + "@noLogsMessage": {}, + "deleteButton": "Delete", + "@deleteButton": {}, + "duplicateButton": "Duplicate", + "@duplicateButton": {}, + "skipAlarmButton": "Skip Next Alarm", + "@skipAlarmButton": {}, + "cancelSkipAlarmButton": "Cancel Skip", + "@cancelSkipAlarmButton": {}, + "dismissAlarmButton": "Dismiss", + "@dismissAlarmButton": {}, + "allFilter": "All", + "@allFilter": {}, + "dateFilterGroup": "Date", + "@dateFilterGroup": {}, + "scheduleDateFilterGroup": "Schedule Date", + "@scheduleDateFilterGroup": {}, + "logTypeFilterGroup": "Type", + "@logTypeFilterGroup": {}, + "createdDateFilterGroup": "Created Date", + "@createdDateFilterGroup": {}, + "todayFilter": "Today", + "@todayFilter": {}, + "tomorrowFilter": "Tomorrow", + "@tomorrowFilter": {}, + "stateFilterGroup": "State", + "@stateFilterGroup": {}, + "activeFilter": "Active", + "@activeFilter": {}, + "inactiveFilter": "Inactive", + "@inactiveFilter": {}, + "snoozedFilter": "Snoozed", + "@snoozedFilter": {}, + "disabledFilter": "Disabled", + "@disabledFilter": {}, + "completedFilter": "Completed", + "@completedFilter": {}, + "runningTimerFilter": "Running", + "@runningTimerFilter": {}, + "pausedTimerFilter": "Paused", + "@pausedTimerFilter": {}, + "stoppedTimerFilter": "Stopped", + "@stoppedTimerFilter": {}, + "sortGroup": "Sort", + "@sortGroup": {}, + "defaultLabel": "Default", + "@defaultLabel": {}, + "remainingTimeDesc": "Least time left", + "@remainingTimeDesc": {}, + "remainingTimeAsc": "Most time left", + "@remainingTimeAsc": {}, + "durationAsc": "Shortest", + "@durationAsc": {}, + "durationDesc": "Longest", + "@durationDesc": {}, + "nameAsc": "Label A-Z", + "@nameAsc": {}, + "nameDesc": "Label Z-A", + "@nameDesc": {}, + "timeOfDayAsc": "Early hours first", + "@timeOfDayAsc": {}, + "timeOfDayDesc": "Late hours first", + "@timeOfDayDesc": {}, + "filterActions": "Filter Actions", + "@filterActions": {}, + "clearFiltersAction": "Clear all filters", + "@clearFiltersAction": {}, + "enableAllFilteredAlarmsAction": "Enable all filtered alarms", + "@enableAllFilteredAlarmsAction": {}, + "disableAllFilteredAlarmsAction": "Disable all filtered alarms", + "@disableAllFilteredAlarmsAction": {}, + "skipAllFilteredAlarmsAction": "Skip all filtered alarms", + "@skipAllFilteredAlarmsAction": {}, + "cancelSkipAllFilteredAlarmsAction": "Cancel skip all filtered alarms", + "@cancelSkipAllFilteredAlarmsAction": {}, + "deleteAllFilteredAction": "Delete all filtered items", + "@deleteAllFilteredAction": {}, + "skippingDescriptionSuffix": "(skipping next occurrence)", + "@skippingDescriptionSuffix": {}, + "alarmDescriptionSnooze": "Snoozed until {date}", + "@alarmDescriptionSnooze": {}, + "alarmDescriptionFinished": "No future dates", + "@alarmDescriptionFinished": {}, + "alarmDescriptionNotScheduled": "Not scheduled", + "@alarmDescriptionNotScheduled": {}, + "alarmDescriptionToday": "Just today", + "@alarmDescriptionToday": {}, + "alarmDescriptionTomorrow": "Just tomorrow", + "@alarmDescriptionTomorrow": {}, + "alarmDescriptionEveryDay": "Every day", + "@alarmDescriptionEveryDay": {}, + "alarmDescriptionWeekend": "Every weekend", + "@alarmDescriptionWeekend": {}, + "stopwatchPrevious": "Previous", + "@stopwatchPrevious": {}, + "alarmDescriptionWeekday": "Every weekday", + "@alarmDescriptionWeekday": {}, + "alarmDescriptionWeekly": "Every {days}", + "@alarmDescriptionWeekly": {}, + "stopwatchFastest": "Fastest", + "@stopwatchFastest": {}, + "alarmDescriptionDays": "On {days}", + "@alarmDescriptionDays": {}, + "alarmDescriptionRange": "{interval, select, daily{Daily} weekly{Weekly} other{Other}} from {startDate} to {endDate}", + "@alarmDescriptionRange": {}, + "stopwatchSlowest": "Slowest", + "@stopwatchSlowest": {}, + "alarmDescriptionDates": "On {date}{count, plural, =0{} =1{ and 1 other date} other{ and {count} other dates}}", + "@alarmDescriptionDates": {}, + "stopwatchAverage": "Average", + "@stopwatchAverage": {}, + "defaultSettingGroup": "Default Settings", + "@defaultSettingGroup": {}, + "alarmsDefaultSettingGroupDescription": "Set default values for new alarms", + "@alarmsDefaultSettingGroupDescription": {}, + "timerDefaultSettingGroupDescription": "Set default values for new timers", + "@timerDefaultSettingGroupDescription": {}, + "filtersSettingGroup": "Filters", + "@filtersSettingGroup": {}, + "showFiltersSetting": "Show Filters", + "@showFiltersSetting": {}, + "showSortSetting": "Show Sort", + "@showSortSetting": {}, + "notificationsSettingGroup": "Notifications", + "@notificationsSettingGroup": {}, + "showUpcomingAlarmNotificationSetting": "Show Upcoming Alarm Notifications", + "@showUpcomingAlarmNotificationSetting": {}, + "upcomingLeadTimeSetting": "Upcoming Lead Time", + "@upcomingLeadTimeSetting": {}, + "showSnoozeNotificationSetting": "Show Snooze Notifications", + "@showSnoozeNotificationSetting": {}, + "showNotificationSetting": "Show Notification", + "@showNotificationSetting": {}, + "presetsSetting": "Presets", + "@presetsSetting": {}, + "newPresetPlaceholder": "New Preset", + "@newPresetPlaceholder": {}, + "dismissActionSetting": "Dismiss Action Type", + "@dismissActionSetting": {}, + "dismissActionSlide": "Slide", + "@dismissActionSlide": {}, + "dismissActionButtons": "Buttons", + "@dismissActionButtons": {}, + "dismissActionAreaButtons": "Area Buttons", + "@dismissActionAreaButtons": {}, + "stopwatchTimeFormatSettingGroup": "Time Format", + "@stopwatchTimeFormatSettingGroup": {}, + "stopwatchShowMillisecondsSetting": "Show Milliseconds", + "@stopwatchShowMillisecondsSetting": {}, + "comparisonLapBarsSettingGroup": "Comparison Lap Bars", + "@comparisonLapBarsSettingGroup": {}, + "showPreviousLapSetting": "Show Previous Lap", + "@showPreviousLapSetting": {}, + "showFastestLapSetting": "Show Fastest Lap", + "@showFastestLapSetting": {}, + "showAverageLapSetting": "Show Average Lap", + "@showAverageLapSetting": {}, + "showSlowestLapSetting": "Show Slowest Lap", + "@showSlowestLapSetting": {}, + "leftHandedSetting": "Left Handed Mode", + "@leftHandedSetting": {}, + "exportSettingsSetting": "Export", + "@exportSettingsSetting": {}, + "exportSettingsSettingDescription": "Export settings to a local file", + "@exportSettingsSettingDescription": {}, + "importSettingsSetting": "Import", + "@importSettingsSetting": {}, + "importSettingsSettingDescription": "Import settings from a local file", + "@importSettingsSettingDescription": {}, + "versionLabel": "Version", + "@versionLabel": {}, + "packageNameLabel": "Package name", + "@packageNameLabel": {}, + "licenseLabel": "License", + "@licenseLabel": {}, + "emailLabel": "Email", + "@emailLabel": {}, + "viewOnGithubLabel": "View on GitHub", + "@viewOnGithubLabel": {}, + "openSourceLicensesSetting": "Open Source Licenses", + "@openSourceLicensesSetting": {}, + "contributorsSetting": "Contributors", + "@contributorsSetting": {}, + "donorsSetting": "Donors", + "@donorsSetting": {}, + "donateButton": "Donate", + "@donateButton": {}, + "addLengthSetting": "Add Length", + "@addLengthSetting": {}, + "relativeTime": "{hours}h {relative, select, ahead{ahead} behind{behind} other{Other}}", + "@relativeTime": {}, + "sameTime": "Same time", + "@sameTime": {}, + "searchSettingPlaceholder": "Search for a setting", + "@searchSettingPlaceholder": {}, + "searchCityPlaceholder": "Search for a city", + "@searchCityPlaceholder": {}, + "cityAlreadyInFavorites": "This city is already in your favorites", + "@cityAlreadyInFavorites": {}, + "durationPickerTitle": "Choose Duration", + "@durationPickerTitle": {}, + "editButton": "Edit", + "@editButton": {}, + "noLapsMessage": "No laps yet", + "@noLapsMessage": {}, + "elapsedTime": "Elapsed Time", + "@elapsedTime": {}, + "mondayFull": "Monday", + "@mondayFull": {}, + "tuesdayFull": "Tuesday", + "@tuesdayFull": {}, + "wednesdayFull": "Wednesday", + "@wednesdayFull": {}, + "thursdayFull": "Thursday", + "@thursdayFull": {}, + "fridayFull": "Friday", + "@fridayFull": {}, + "saturdayFull": "Saturday", + "@saturdayFull": {}, + "sundayFull": "Sunday", + "@sundayFull": {}, + "mondayShort": "Mon", + "@mondayShort": {}, + "tuesdayShort": "Tue", + "@tuesdayShort": {}, + "wednesdayShort": "Wed", + "@wednesdayShort": {}, + "thursdayShort": "Thu", + "@thursdayShort": {}, + "fridayShort": "Fri", + "@fridayShort": {}, + "saturdayShort": "Sat", + "@saturdayShort": {}, + "sundayShort": "Sun", + "@sundayShort": {}, + "mondayLetter": "M", + "@mondayLetter": {}, + "tuesdayLetter": "T", + "@tuesdayLetter": {}, + "wednesdayLetter": "W", + "@wednesdayLetter": {}, + "thursdayLetter": "T", + "@thursdayLetter": {}, + "fridayLetter": "F", + "@fridayLetter": {}, + "saturdayLetter": "S", + "@saturdayLetter": {}, + "sundayLetter": "S", + "@sundayLetter": {}, + "donateDescription": "Donate to support the development of the app", + "@donateDescription": {}, + "donorsDescription": "Our generous patreons", + "@donorsDescription": {}, + "contributorsDescription": "People who make this app possible", + "@contributorsDescription": {}, + "widgetsSettingGroup": "Widgets", + "@widgetsSettingGroup": {}, + "digitalClockSettingGroup": "Digital Clock", + "@digitalClockSettingGroup": {}, + "layoutSettingGroup": "Layout", + "@layoutSettingGroup": {}, + "timeSizeSetting": "Time Size", + "@timeSizeSetting": {}, + "dateSizeSetting": "Date Size", + "@dateSizeSetting": {}, + "textSettingGroup": "Text", + "@textSettingGroup": {}, + "showDateSetting": "Show Date", + "@showDateSetting": {}, + "settingsTitle": "Settings", + "@settingsTitle": {} +} diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb new file mode 100644 index 00000000..e36a5e15 --- /dev/null +++ b/lib/l10n/app_es.arb @@ -0,0 +1,602 @@ +{ + "clockTitle": "Reloj", + "@clockTitle": {}, + "alarmTitle": "Alarma", + "@alarmTitle": {}, + "timerTitle": "Temporizador", + "@timerTitle": {}, + "stopwatchTitle": "Cronómetro", + "@stopwatchTitle": {}, + "generalSettingGroup": "General", + "@generalSettingGroup": {}, + "appearanceSettingGroup": "Apariencia", + "@appearanceSettingGroup": {}, + "accessibilitySettingGroup": "Accesibilidad", + "@accessibilitySettingGroup": {}, + "backupSettingGroup": "Ajustes", + "@backupSettingGroup": {}, + "developerOptionsSettingGroup": "Opciones de desarrollador", + "@developerOptionsSettingGroup": {}, + "aboutSettingGroup": "Acerca de", + "@aboutSettingGroup": {}, + "restoreSettingGroup": "Restaurar a los valores predeterminados", + "@restoreSettingGroup": {}, + "displaySettingGroup": "Pantalla", + "@displaySettingGroup": {}, + "reliabilitySettingGroup": "Fiabilidad", + "@reliabilitySettingGroup": {}, + "colorsSettingGroup": "Colores", + "@colorsSettingGroup": {}, + "styleSettingGroup": "Estilo", + "@styleSettingGroup": {}, + "useMaterialYouColorSetting": "Utilizar Material You", + "@useMaterialYouColorSetting": {}, + "materialBrightnessSetting": "Brillo", + "@materialBrightnessSetting": {}, + "overrideAccentSetting": "Anular color acentuado", + "@overrideAccentSetting": {}, + "useMaterialStyleSetting": "Utilizar Material Style", + "@useMaterialStyleSetting": {}, + "styleThemeSetting": "Estilo del tema", + "@styleThemeSetting": {}, + "systemDarkModeSetting": "Modo oscuro del sistema", + "@systemDarkModeSetting": {}, + "colorSchemeSetting": "Esquema de colores", + "@colorSchemeSetting": {}, + "darkColorSchemeSetting": "Esquema de colores oscuros", + "@darkColorSchemeSetting": {}, + "clockSettingGroup": "Reloj", + "@clockSettingGroup": {}, + "timerSettingGroup": "Temporizador", + "@timerSettingGroup": {}, + "stopwatchSettingGroup": "Cronómetro", + "@stopwatchSettingGroup": {}, + "generalSettingGroupDescription": "Configurar los ajustes de la aplicación, como el formato de la hora", + "@generalSettingGroupDescription": {}, + "appearanceSettingGroupDescription": "Establecer temas, colores y cambiar el diseño", + "@appearanceSettingGroupDescription": {}, + "backupSettingGroupDescription": "Exporta o importa tu configuración localmente", + "@backupSettingGroupDescription": {}, + "selectTime": "Seleccione la hora", + "@selectTime": {}, + "cancelButton": "Cancelar", + "@cancelButton": {}, + "customizeButton": "Personalizar", + "@customizeButton": {}, + "saveButton": "Guardar", + "@saveButton": {}, + "labelField": "Etiqueta", + "@labelField": {}, + "labelFieldPlaceholder": "Añadir una etiqueta", + "@labelFieldPlaceholder": {}, + "alarmScheduleSettingGroup": "Programar", + "@alarmScheduleSettingGroup": {}, + "scheduleTypeField": "Tipo", + "@scheduleTypeField": {}, + "scheduleTypeOnce": "Una vez", + "@scheduleTypeOnce": {}, + "scheduleTypeDaily": "Diariamente", + "@scheduleTypeDaily": {}, + "scheduleTypeOnceDescription": "Sonará a la siguiente hora fijada", + "@scheduleTypeOnceDescription": {}, + "scheduleTypeDailyDescription": "Sonará todos los días", + "@scheduleTypeDailyDescription": {}, + "scheduleTypeWeek": "En días de la semana especificados", + "@scheduleTypeWeek": {}, + "scheduleTypeWeekDescription": "Se repetirá los días de la semana especificados", + "@scheduleTypeWeekDescription": {}, + "scheduleTypeRange": "Intervalo de fechas", + "@scheduleTypeRange": {}, + "scheduleTypeDateDescription": "Se repetirá en las fechas especificadas", + "@scheduleTypeDateDescription": {}, + "scheduleTypeRangeDescription": "Se repetirá durante el intervalo de fechas especificado", + "@scheduleTypeRangeDescription": {}, + "soundSettingGroup": "Sonido", + "@soundSettingGroup": {}, + "settingGroupMore": "Más", + "@settingGroupMore": {}, + "melodySetting": "Melodía", + "@melodySetting": {}, + "vibrationSetting": "Vibración", + "@vibrationSetting": {}, + "audioChannelSetting": "Canal de audio", + "@audioChannelSetting": {}, + "volumeSetting": "Volumen", + "@volumeSetting": {}, + "risingVolumeSetting": "Volumen en aumento", + "@risingVolumeSetting": {}, + "snoozeSettingGroup": "Repetir la alarma", + "@snoozeSettingGroup": {}, + "snoozeEnableSetting": "Activado", + "@snoozeEnableSetting": {}, + "snoozeLengthSetting": "Duración", + "@snoozeLengthSetting": {}, + "snoozePreventDisablingSetting": "Evitar la desactivación", + "@snoozePreventDisablingSetting": {}, + "settings": "Ajustes", + "@settings": {}, + "tasksSetting": "Tareas", + "@tasksSetting": {}, + "noItemMessage": "No hay {items} añadidos aún", + "@noItemMessage": {}, + "chooseTaskTitle": "Seleccione la tarea que desea añadir", + "@chooseTaskTitle": {}, + "retypeTask": "Repetir el texto", + "@retypeTask": {}, + "sequenceTask": "Secuencia", + "@sequenceTask": {}, + "taskTryButton": "Probar", + "@taskTryButton": {}, + "mathTaskDifficultySetting": "Dificultad", + "@mathTaskDifficultySetting": {}, + "retypeNumberChars": "Número de caracteres", + "@retypeNumberChars": {}, + "retypeIncludeNumSetting": "Números incluidos", + "@retypeIncludeNumSetting": {}, + "retypeLowercaseSetting": "Incluir minúsculas", + "@retypeLowercaseSetting": {}, + "sequenceLengthSetting": "Duración de la secuencia", + "@sequenceLengthSetting": {}, + "sequenceGridSizeSetting": "Tamaño de la cuadrícula", + "@sequenceGridSizeSetting": {}, + "saveReminderAlert": "¿Quieres salir sin guardar?", + "@saveReminderAlert": {}, + "yesButton": "Sí", + "@yesButton": {}, + "noButton": "No", + "@noButton": {}, + "deleteButton": "Borrar", + "@deleteButton": {}, + "duplicateButton": "Duplicar", + "@duplicateButton": {}, + "skipAlarmButton": "Omitir la siguiente alarma", + "@skipAlarmButton": {}, + "todayFilter": "Hoy", + "@todayFilter": {}, + "tomorrowFilter": "Mañana", + "@tomorrowFilter": {}, + "disabledFilter": "Desactivar", + "@disabledFilter": {}, + "completedFilter": "Terminada", + "@completedFilter": {}, + "allFilter": "Todas", + "@allFilter": {}, + "whileSnoozedSettingGroup": "Mientras estás dormido", + "@whileSnoozedSettingGroup": {}, + "mathTask": "Problemas matemáticos", + "@mathTask": {}, + "snoozedFilter": "Pospuesto", + "@snoozedFilter": {}, + "skippingDescriptionSuffix": "(omitir la siguiente aparición)", + "@skippingDescriptionSuffix": {}, + "alarmDescriptionSnooze": "Posponer hasta {date}", + "@alarmDescriptionSnooze": {}, + "alarmDescriptionFinished": "Sin fechas futuras", + "@alarmDescriptionFinished": {}, + "alarmDescriptionNotScheduled": "No programado", + "@alarmDescriptionNotScheduled": {}, + "alarmDescriptionToday": "Hoy mismo", + "@alarmDescriptionToday": {}, + "alarmDescriptionTomorrow": "Mañana mismo", + "@alarmDescriptionTomorrow": {}, + "alarmDescriptionEveryDay": "Cada día", + "@alarmDescriptionEveryDay": {}, + "alarmDescriptionWeekend": "Cada semana", + "@alarmDescriptionWeekend": {}, + "stopwatchPrevious": "Anterior", + "@stopwatchPrevious": {}, + "alarmDescriptionWeekday": "Cada día de la semana", + "@alarmDescriptionWeekday": {}, + "stopwatchFastest": "La más rápida", + "@stopwatchFastest": {}, + "alarmDescriptionDays": "En {days}", + "@alarmDescriptionDays": {}, + "stopwatchSlowest": "La más lenta", + "@stopwatchSlowest": {}, + "alarmDescriptionRange": "{interval, select, daily{A diario} weekly{Semanalmente} other{Other}} desde {startDate} a {endDate}", + "@alarmDescriptionRange": {}, + "alarmDescriptionDates": "En {date}{count, plural, =0{} =1{ y otra fecha} other{ y {count} otras fechas}}", + "@alarmDescriptionDates": {}, + "stopwatchAverage": "Promedio", + "@stopwatchAverage": {}, + "system": "Sistema", + "@system": {}, + "timeFormatSetting": "Formato de la hora", + "@timeFormatSetting": {}, + "timeFormat12": "12 horas", + "@timeFormat12": {}, + "timeFormat24": "24 horas", + "@timeFormat24": {}, + "timeFormatDevice": "Ajustes del dispositivo", + "@timeFormatDevice": {}, + "showSecondsSetting": "Mostrar los segundos", + "@showSecondsSetting": {}, + "timePickerSetting": "Selector de tiempo", + "@timePickerSetting": {}, + "pickerDial": "Marcar", + "@pickerDial": {}, + "pickerInput": "Entrada", + "@pickerInput": {}, + "pickerSpinner": "Spinner", + "@pickerSpinner": {}, + "durationPickerSetting": "Selector de duración", + "@durationPickerSetting": {}, + "pickerRings": "Tonos", + "@pickerRings": {}, + "swipeActionCardActionDescription": "Desliza el dedo a izquierda o derecha en la tarjeta para realizar acciones", + "@swipeActionCardActionDescription": {}, + "swipActionSwitchTabs": "Cambiar pestañas", + "@swipActionSwitchTabs": {}, + "swipeActionSwitchTabsDescription": "Pasar de una pestaña a otra", + "@swipeActionSwitchTabsDescription": {}, + "melodiesSetting": "Melodías", + "@melodiesSetting": {}, + "tagsSetting": "Etiquetas", + "@tagsSetting": {}, + "vendorSetting": "Ajustes del proveedor", + "@vendorSetting": {}, + "vendorSettingDescription": "Desactivar manualmente las optimizaciones específicas del proveedor", + "@vendorSettingDescription": {}, + "batteryOptimizationSetting": "Desactivar la optimización de la batería", + "@batteryOptimizationSetting": {}, + "allowNotificationSetting": "Permitir notificaciones", + "@allowNotificationSetting": {}, + "autoStartSetting": "Inicio automático", + "@autoStartSetting": {}, + "animationSettingGroup": "Animaciones", + "@animationSettingGroup": {}, + "animationSpeedSetting": "Velocidad de las animaciones", + "@animationSpeedSetting": {}, + "extraAnimationSetting": "Animaciones adicionales", + "@extraAnimationSetting": {}, + "nameField": "Nombre", + "@nameField": {}, + "colorSetting": "Color", + "@colorSetting": {}, + "textColorSetting": "Texto", + "@textColorSetting": {}, + "colorSchemeNamePlaceholder": "Esquema de colores", + "@colorSchemeNamePlaceholder": {}, + "colorSchemeBackgroundSettingGroup": "Fondo", + "@colorSchemeBackgroundSettingGroup": {}, + "colorSchemeAccentSettingGroup": "Acentuar", + "@colorSchemeAccentSettingGroup": {}, + "colorSchemeErrorSettingGroup": "Error", + "@colorSchemeErrorSettingGroup": {}, + "colorSchemeCardSettingGroup": "Tarjeta", + "@colorSchemeCardSettingGroup": {}, + "colorSchemeOutlineSettingGroup": "Descripción", + "@colorSchemeOutlineSettingGroup": {}, + "colorSchemeShadowSettingGroup": "Sombra", + "@colorSchemeShadowSettingGroup": {}, + "styleThemeNamePlaceholder": "Estilo del tema", + "@styleThemeNamePlaceholder": {}, + "styleThemeShadowSettingGroup": "Sombra", + "@styleThemeShadowSettingGroup": {}, + "styleThemeShapeSettingGroup": "Forma", + "@styleThemeShapeSettingGroup": {}, + "styleThemeElevationSetting": "Elevación", + "@styleThemeElevationSetting": {}, + "styleThemeRadiusSetting": "Redondez de las esquinas", + "@styleThemeRadiusSetting": {}, + "styleThemeOpacitySetting": "Opacidad", + "@styleThemeOpacitySetting": {}, + "styleThemeBlurSetting": "Difuminar", + "@styleThemeBlurSetting": {}, + "styleThemeSpreadSetting": "Envergadura", + "@styleThemeSpreadSetting": {}, + "styleThemeOutlineSettingGroup": "Descripción", + "@styleThemeOutlineSettingGroup": {}, + "styleThemeOutlineWidthSetting": "Ancho", + "@styleThemeOutlineWidthSetting": {}, + "showIstantAlarmButtonSetting": "Mostrar botón de alarma instantánea", + "@showIstantAlarmButtonSetting": {}, + "showIstantTimerButtonSetting": "Mostrar botón de temporizador instantáneo", + "@showIstantTimerButtonSetting": {}, + "maxLogsSetting": "Registros máximos", + "@maxLogsSetting": {}, + "alarmLogSetting": "Registros de alarmas", + "@alarmLogSetting": {}, + "resetButton": "Restablecer", + "@resetButton": {}, + "previewLabel": "Vista previa", + "@previewLabel": {}, + "errorLabel": "Error", + "@errorLabel": {}, + "materialBrightnessSystem": "Sistema", + "@materialBrightnessSystem": {}, + "materialBrightnessLight": "Claro", + "@materialBrightnessLight": {}, + "materialBrightnessDark": "Oscuro", + "@materialBrightnessDark": {}, + "accentColorSetting": "Acentuar el color", + "@accentColorSetting": {}, + "alarmWeekdaysSetting": "Días de la semana", + "@alarmWeekdaysSetting": {}, + "mondayLetter": "L", + "@mondayLetter": {}, + "tuesdayLetter": "M", + "@tuesdayLetter": {}, + "colorSchemeUseAccentAsShadowSetting": "Usar acento como sombra", + "@colorSchemeUseAccentAsShadowSetting": {}, + "thursdayLetter": "J", + "@thursdayLetter": {}, + "fridayLetter": "V", + "@fridayLetter": {}, + "saturdayLetter": "S", + "@saturdayLetter": {}, + "sundayLetter": "D", + "@sundayLetter": {}, + "alarmDatesSetting": "Fechas", + "@alarmDatesSetting": {}, + "alarmRangeSetting": "Rango de fechas", + "@alarmRangeSetting": {}, + "alarmIntervalSetting": "Intervalo", + "@alarmIntervalSetting": {}, + "alarmIntervalDaily": "A diario", + "@alarmIntervalDaily": {}, + "alarmIntervalWeekly": "Semanalmente", + "@alarmIntervalWeekly": {}, + "soundAndVibrationSettingGroup": "Sonido y vibración", + "@soundAndVibrationSettingGroup": {}, + "audioChannelAlarm": "Alarma", + "@audioChannelAlarm": {}, + "audioChannelNotification": "Notificación", + "@audioChannelNotification": {}, + "audioChannelRingtone": "Tono de llamada", + "@audioChannelRingtone": {}, + "audioChannelMedia": "Medio", + "@audioChannelMedia": {}, + "maxSnoozesSetting": "Máximo de repeticiones", + "@maxSnoozesSetting": {}, + "snoozePreventDeletionSetting": "Prevenir la eliminación", + "@snoozePreventDeletionSetting": {}, + "mathEasyDifficulty": "Fácil (X+Y)", + "@mathEasyDifficulty": {}, + "mathMediumDifficulty": "Medio (X × Y)", + "@mathMediumDifficulty": {}, + "mathHardDifficulty": "Difícil (X × Y + Z)", + "@mathHardDifficulty": {}, + "mathVeryHardDifficulty": "Muy difícil (X × Y × Z)", + "@mathVeryHardDifficulty": {}, + "numberOfProblemsSetting": "Número de problemas", + "@numberOfProblemsSetting": {}, + "defaultSettingGroup": "Ajustes por defecto", + "@defaultSettingGroup": {}, + "alarmsDefaultSettingGroupDescription": "Establecer valores predeterminados para nuevas alarmas", + "@alarmsDefaultSettingGroupDescription": {}, + "timerDefaultSettingGroupDescription": "Establecer valores predeterminados para nuevos temporizadores", + "@timerDefaultSettingGroupDescription": {}, + "filtersSettingGroup": "Filtros", + "@filtersSettingGroup": {}, + "showSortSetting": "Mostrar ordenar", + "@showSortSetting": {}, + "notificationsSettingGroup": "Notificaciones", + "@notificationsSettingGroup": {}, + "upcomingLeadTimeSetting": "Próximo plazo", + "@upcomingLeadTimeSetting": {}, + "showSnoozeNotificationSetting": "Mostrar notificaciones de repetición", + "@showSnoozeNotificationSetting": {}, + "showNotificationSetting": "Mostrar la notificación", + "@showNotificationSetting": {}, + "presetsSetting": "Ajustes preestablecidos", + "@presetsSetting": {}, + "newPresetPlaceholder": "Nuevos ajustes preestablecidos", + "@newPresetPlaceholder": {}, + "dismissActionButtons": "Botones", + "@dismissActionButtons": {}, + "stopwatchTimeFormatSettingGroup": "Formato de la hora", + "@stopwatchTimeFormatSettingGroup": {}, + "stopwatchShowMillisecondsSetting": "Mostrar milisegundos", + "@stopwatchShowMillisecondsSetting": {}, + "showFastestLapSetting": "Mostrar vuelta más rápida", + "@showFastestLapSetting": {}, + "showPreviousLapSetting": "Mostrar vuelta anterior", + "@showPreviousLapSetting": {}, + "comparisonLapBarsSettingGroup": "Comparar las vueltas", + "@comparisonLapBarsSettingGroup": {}, + "showAverageLapSetting": "Mostrar vuelta promedio", + "@showAverageLapSetting": {}, + "showSlowestLapSetting": "Mostrar vuelta más lenta", + "@showSlowestLapSetting": {}, + "leftHandedSetting": "Modo para zurdos", + "@leftHandedSetting": {}, + "exportSettingsSetting": "Exportar", + "@exportSettingsSetting": {}, + "exportSettingsSettingDescription": "Exportar ajustes a un archivo local", + "@exportSettingsSettingDescription": {}, + "importSettingsSetting": "Importar", + "@importSettingsSetting": {}, + "importSettingsSettingDescription": "Importar ajustes desde un archivo local", + "@importSettingsSettingDescription": {}, + "versionLabel": "Versión", + "@versionLabel": {}, + "packageNameLabel": "Nombre del paquete", + "@packageNameLabel": {}, + "licenseLabel": "Licencia", + "@licenseLabel": {}, + "viewOnGithubLabel": "Ver en GitHub", + "@viewOnGithubLabel": {}, + "addLengthSetting": "Agregar longitud", + "@addLengthSetting": {}, + "dismissActionAreaButtons": "Zona de controles", + "@dismissActionAreaButtons": {}, + "languageSetting": "Idioma", + "@languageSetting": {}, + "dateFormatSetting": "Formato de la fecha", + "@dateFormatSetting": {}, + "swipeActionSetting": "Acción de deslizar", + "@swipeActionSetting": {}, + "swipActionCardAction": "Acciones con tarjetas", + "@swipActionCardAction": {}, + "batteryOptimizationSettingDescription": "Desactiva la optimización de la batería de esta aplicación para evitar que las alarmas se retrasen", + "@batteryOptimizationSettingDescription": {}, + "alarmDeleteAfterRingingSetting": "Eliminar después de descartar", + "@alarmDeleteAfterRingingSetting": {}, + "timeToFullVolumeSetting": "Tiempo hasta el volumen máximo", + "@timeToFullVolumeSetting": {}, + "logsSettingGroup": "Registros", + "@logsSettingGroup": {}, + "scheduleTypeDate": "En fechas específicas", + "@scheduleTypeDate": {}, + "showUpcomingAlarmNotificationSetting": "Mostrar próximas notificaciones de alarma", + "@showUpcomingAlarmNotificationSetting": {}, + "showFiltersSetting": "Mostrar los filtros", + "@showFiltersSetting": {}, + "allowNotificationSettingDescription": "Permitir notificaciones en la pantalla de bloqueo para alarmas y temporizadores", + "@allowNotificationSettingDescription": {}, + "autoStartSettingDescription": "Algunos dispositivos requieren que el inicio automático esté activado para que las alarmas suenen mientras la aplicación está cerrada", + "@autoStartSettingDescription": {}, + "cardLabel": "Tarjeta", + "@cardLabel": {}, + "wednesdayLetter": "X", + "@wednesdayLetter": {}, + "alarmDeleteAfterFinishingSetting": "Eliminar después de terminar", + "@alarmDeleteAfterFinishingSetting": {}, + "dismissActionSetting": "Descartar tipo de acción", + "@dismissActionSetting": {}, + "dismissActionSlide": "Deslizar", + "@dismissActionSlide": {}, + "emailLabel": "Correo electrónico", + "@emailLabel": {}, + "cannotDisableAlarmWhileSnoozedSnackbar": "No se puede desactivar la alarma mientras está pospuesta", + "@cannotDisableAlarmWhileSnoozedSnackbar": {}, + "noTimerMessage": "No se crearon temporizadores", + "@noTimerMessage": {}, + "noTaskMessage": "No se crearon tareas", + "@noTaskMessage": {}, + "timeOfDayAsc": "Primero las primeras horas", + "@timeOfDayAsc": {}, + "disableAllFilteredAlarmsAction": "Deshabilitar todas las alarmas filtradas", + "@disableAllFilteredAlarmsAction": {}, + "noAlarmMessage": "No se crearon alarmas", + "@noAlarmMessage": {}, + "noStopwatchMessage": "No se crearon cronómetros", + "@noStopwatchMessage": {}, + "noPresetsMessage": "No se han creado ajustes preestablecidos", + "@noPresetsMessage": {}, + "noLogsMessage": "Sin registros de alarma", + "@noLogsMessage": {}, + "dateFilterGroup": "Fecha", + "@dateFilterGroup": {}, + "stateFilterGroup": "Estado", + "@stateFilterGroup": {}, + "activeFilter": "Activa", + "@activeFilter": {}, + "sortGroup": "Ordenar", + "@sortGroup": {}, + "defaultLabel": "Por defecto", + "@defaultLabel": {}, + "remainingTimeDesc": "Queda menos tiempo", + "@remainingTimeDesc": {}, + "remainingTimeAsc": "Queda más tiempo", + "@remainingTimeAsc": {}, + "nameAsc": "Nombre A-Z", + "@nameAsc": {}, + "nameDesc": "Nombre Z-A", + "@nameDesc": {}, + "timeOfDayDesc": "Primero las últimas horas", + "@timeOfDayDesc": {}, + "filterActions": "Filtrar acciones", + "@filterActions": {}, + "clearFiltersAction": "Limpiar todos los filtros", + "@clearFiltersAction": {}, + "enableAllFilteredAlarmsAction": "Habilitar todas las alarmas filtradas", + "@enableAllFilteredAlarmsAction": {}, + "cancelSkipAllFilteredAlarmsAction": "No omitir todas las alarmas filtradas", + "@cancelSkipAllFilteredAlarmsAction": {}, + "skipAllFilteredAlarmsAction": "Omitir todas las alarmas filtradas", + "@skipAllFilteredAlarmsAction": {}, + "deleteAllFilteredAction": "Eliminar todos los elementos filtrados", + "@deleteAllFilteredAction": {}, + "timePickerModeButton": "Modo", + "@timePickerModeButton": {}, + "colorSchemeUseAccentAsOutlineSetting": "Utilice énfasis para los bordes", + "@colorSchemeUseAccentAsOutlineSetting": {}, + "accentLabel": "Acentuar", + "@accentLabel": {}, + "scheduleDateFilterGroup": "Fecha de programacion", + "@scheduleDateFilterGroup": {}, + "logTypeFilterGroup": "Tipo", + "@logTypeFilterGroup": {}, + "createdDateFilterGroup": "Fecha de creación", + "@createdDateFilterGroup": {}, + "inactiveFilter": "Inactivo", + "@inactiveFilter": {}, + "runningTimerFilter": "Ejecutándose", + "@runningTimerFilter": {}, + "pausedTimerFilter": "Pausado", + "@pausedTimerFilter": {}, + "stoppedTimerFilter": "Detenido", + "@stoppedTimerFilter": {}, + "durationAsc": "Más corto", + "@durationAsc": {}, + "durationDesc": "Más largo", + "@durationDesc": {}, + "cancelSkipAlarmButton": "Cancelar omitir", + "@cancelSkipAlarmButton": {}, + "dismissAlarmButton": "Descartar", + "@dismissAlarmButton": {}, + "sameTime": "Al mismo tiempo", + "@sameTime": {}, + "searchCityPlaceholder": "Buscar una ciudad", + "@searchCityPlaceholder": {}, + "durationPickerTitle": "Elige la duración", + "@durationPickerTitle": {}, + "relativeTime": "{hours}h {relative, select, ahead{adelante} behind{detrás} other{Other}}", + "@relativeTime": {}, + "thursdayFull": "Jueves", + "@thursdayFull": {}, + "elapsedTime": "Tiempo transcurrido", + "@elapsedTime": {}, + "wednesdayFull": "Miércoles", + "@wednesdayFull": {}, + "mondayShort": "LU", + "@mondayShort": {}, + "thursdayShort": "JU", + "@thursdayShort": {}, + "fridayShort": "VI", + "@fridayShort": {}, + "sundayShort": "DO", + "@sundayShort": {}, + "editButton": "Editar", + "@editButton": {}, + "noLapsMessage": "Aún no hay vueltas", + "@noLapsMessage": {}, + "tuesdayFull": "Martes", + "@tuesdayFull": {}, + "fridayFull": "Viernes", + "@fridayFull": {}, + "saturdayFull": "Sábado", + "@saturdayFull": {}, + "sundayFull": "Domingo", + "@sundayFull": {}, + "tuesdayShort": "MA", + "@tuesdayShort": {}, + "wednesdayShort": "MI", + "@wednesdayShort": {}, + "saturdayShort": "SA", + "@saturdayShort": {}, + "alarmDescriptionWeekly": "Cada {days}", + "@alarmDescriptionWeekly": {}, + "searchSettingPlaceholder": "Buscar un ajuste", + "@searchSettingPlaceholder": {}, + "cityAlreadyInFavorites": "Esta ciudad ya está en tus favoritos", + "@cityAlreadyInFavorites": {}, + "mondayFull": "Lunes", + "@mondayFull": {}, + "openSourceLicensesSetting": "Licencias de código abierto", + "@openSourceLicensesSetting": {}, + "contributorsSetting": "Colaboradores", + "@contributorsSetting": {}, + "donorsSetting": "Donantes", + "@donorsSetting": {}, + "donateButton": "Donar", + "@donateButton": {}, + "donateDescription": "Donar para apoyar el desarrollo de la aplicación", + "@donateDescription": {}, + "donorsDescription": "Nuestros generosos mecenas", + "@donorsDescription": {}, + "contributorsDescription": "Personas que hacen posible esta aplicación", + "@contributorsDescription": {} +} diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb new file mode 100644 index 00000000..7854792d --- /dev/null +++ b/lib/l10n/app_fr.arb @@ -0,0 +1,610 @@ +{ + "stopwatchTitle": "Chronomètre", + "@stopwatchTitle": { + "description": "Title of the stopwatch screen" + }, + "colorsSettingGroup": "Couleurs", + "@colorsSettingGroup": {}, + "generalSettingGroupDescription": "Paramètres généraux de l'application tels que le format de l'heure", + "@generalSettingGroupDescription": {}, + "customizeButton": "Personnaliser", + "@customizeButton": {}, + "scheduleTypeDailyDescription": "Sonnera tous les jours", + "@scheduleTypeDailyDescription": {}, + "vibrationSetting": "Vibration", + "@vibrationSetting": {}, + "audioChannelSetting": "Canal audio", + "@audioChannelSetting": {}, + "systemDarkModeSetting": "Thème sombre du système", + "@systemDarkModeSetting": {}, + "clockTitle": "Horloge", + "@clockTitle": { + "description": "Title of the clock screen" + }, + "alarmTitle": "Alarme", + "@alarmTitle": { + "description": "Title of the alarm screen" + }, + "timerTitle": "Minuteur", + "@timerTitle": { + "description": "Title of the timer screen" + }, + "generalSettingGroup": "Général", + "@generalSettingGroup": {}, + "appearanceSettingGroup": "Apparence", + "@appearanceSettingGroup": {}, + "accessibilitySettingGroup": "Accessibilité", + "@accessibilitySettingGroup": {}, + "backupSettingGroup": "Paramètres", + "@backupSettingGroup": {}, + "developerOptionsSettingGroup": "Options pour les développeurs", + "@developerOptionsSettingGroup": {}, + "aboutSettingGroup": "À propos", + "@aboutSettingGroup": {}, + "restoreSettingGroup": "Restaurer les valeurs par défaut", + "@restoreSettingGroup": {}, + "displaySettingGroup": "Affichage", + "@displaySettingGroup": {}, + "styleSettingGroup": "Style", + "@styleSettingGroup": {}, + "useMaterialYouColorSetting": "Utiliser Material You", + "@useMaterialYouColorSetting": {}, + "materialBrightnessSetting": "Luminosité", + "@materialBrightnessSetting": {}, + "overrideAccentSetting": "Écraser la couleur d'accentuation", + "@overrideAccentSetting": {}, + "useMaterialStyleSetting": "Utiliser le style Material", + "@useMaterialStyleSetting": {}, + "styleThemeSetting": "Thème du style", + "@styleThemeSetting": {}, + "colorSchemeSetting": "Schéma de couleur", + "@colorSchemeSetting": {}, + "darkColorSchemeSetting": "Schéma de couleur sombre", + "@darkColorSchemeSetting": {}, + "clockSettingGroup": "Horloge", + "@clockSettingGroup": {}, + "timerSettingGroup": "Minuteur", + "@timerSettingGroup": {}, + "stopwatchSettingGroup": "Chronomètre", + "@stopwatchSettingGroup": {}, + "appearanceSettingGroupDescription": "Modifiez le thème, les couleurs et la disposition", + "@appearanceSettingGroupDescription": {}, + "backupSettingGroupDescription": "Exportez ou importez vos paramètres", + "@backupSettingGroupDescription": {}, + "selectTime": "Sélectionner l'heure", + "@selectTime": {}, + "cancelButton": "Annuler", + "@cancelButton": {}, + "saveButton": "Enregistrer", + "@saveButton": {}, + "labelField": "Libellé", + "@labelField": {}, + "labelFieldPlaceholder": "Ajouter un libellé", + "@labelFieldPlaceholder": {}, + "scheduleTypeField": "Type", + "@scheduleTypeField": {}, + "scheduleTypeOnce": "Une fois", + "@scheduleTypeOnce": {}, + "scheduleTypeDaily": "Tous les jours", + "@scheduleTypeDaily": {}, + "scheduleTypeOnceDescription": "Sonnera à la prochaine occurrence de l'heure", + "@scheduleTypeOnceDescription": {}, + "scheduleTypeWeek": "À des jours spécifiques", + "@scheduleTypeWeek": {}, + "scheduleTypeRange": "Période", + "@scheduleTypeRange": {}, + "scheduleTypeDateDescription": "Se répétera aux dates définies", + "@scheduleTypeDateDescription": {}, + "scheduleTypeWeekDescription": "Se répétera aux jours définis de la semaine", + "@scheduleTypeWeekDescription": {}, + "reliabilitySettingGroup": "Fiabilité", + "@reliabilitySettingGroup": {}, + "alarmScheduleSettingGroup": "Planifier", + "@alarmScheduleSettingGroup": {}, + "soundSettingGroup": "Son", + "@soundSettingGroup": {}, + "settingGroupMore": "Plus", + "@settingGroupMore": {}, + "melodySetting": "Mélodie", + "@melodySetting": {}, + "volumeSetting": "Volume", + "@volumeSetting": {}, + "risingVolumeSetting": "Volume progressif", + "@risingVolumeSetting": {}, + "snoozeSettingGroup": "Répétition", + "@snoozeSettingGroup": {}, + "snoozeEnableSetting": "Activée", + "@snoozeEnableSetting": {}, + "snoozeLengthSetting": "Intervalle", + "@snoozeLengthSetting": {}, + "whileSnoozedSettingGroup": "Pendant l'intervalle", + "@whileSnoozedSettingGroup": {}, + "snoozePreventDisablingSetting": "Empêcher la désactivation", + "@snoozePreventDisablingSetting": {}, + "settings": "Paramètres", + "@settings": {}, + "tasksSetting": "Tâches", + "@tasksSetting": {}, + "noItemMessage": "Aucun {items} ajouté pour le moment", + "@noItemMessage": {}, + "chooseTaskTitle": "Sélectionnez une tâche à ajouter", + "@chooseTaskTitle": {}, + "mathTask": "Problèmes de math", + "@mathTask": {}, + "retypeTask": "Retaper le texte", + "@retypeTask": {}, + "sequenceTask": "Séquence", + "@sequenceTask": {}, + "taskTryButton": "Essayer", + "@taskTryButton": {}, + "mathTaskDifficultySetting": "Difficulté", + "@mathTaskDifficultySetting": {}, + "scheduleTypeRangeDescription": "Se répétera pendant la période définie", + "@scheduleTypeRangeDescription": {}, + "skippingDescriptionSuffix": "(prochaine alarme ignorée)", + "@skippingDescriptionSuffix": {}, + "alarmDescriptionSnooze": "Ignorée jusqu'au {date}", + "@alarmDescriptionSnooze": {}, + "alarmDescriptionFinished": "Désactivée", + "@alarmDescriptionFinished": {}, + "alarmDescriptionNotScheduled": "Non planifiée", + "@alarmDescriptionNotScheduled": {}, + "alarmDescriptionToday": "Aujourd'hui uniquement", + "@alarmDescriptionToday": {}, + "alarmDescriptionTomorrow": "Demain uniquement", + "@alarmDescriptionTomorrow": {}, + "alarmDescriptionEveryDay": "Tous les jours", + "@alarmDescriptionEveryDay": {}, + "alarmDescriptionWeekend": "Tous les weekends", + "@alarmDescriptionWeekend": {}, + "stopwatchPrevious": "Précédent", + "@stopwatchPrevious": {}, + "alarmDescriptionWeekday": "Tous les jours", + "@alarmDescriptionWeekday": {}, + "stopwatchFastest": "Le plus rapide", + "@stopwatchFastest": {}, + "alarmDescriptionDays": "Tous les {days}", + "@alarmDescriptionDays": {}, + "alarmDescriptionRange": "{interval, select, daily{Tous les jours} weekly{Toutes les semaines} other{Other}} du {startDate} au {endDate}", + "@alarmDescriptionRange": {}, + "stopwatchSlowest": "Le plus lent", + "@stopwatchSlowest": {}, + "alarmDescriptionDates": "Le {date}{count, plural, =0{} =1{ et 1 autre date} other{ et {count} autres dates}}", + "@alarmDescriptionDates": {}, + "stopwatchAverage": "Moyenne", + "@stopwatchAverage": {}, + "system": "Système", + "@system": {}, + "languageSetting": "Langue", + "@languageSetting": {}, + "dateFormatSetting": "Format des dates", + "@dateFormatSetting": {}, + "timeFormatSetting": "Format de l'heure", + "@timeFormatSetting": {}, + "timeFormat12": "12 heures", + "@timeFormat12": {}, + "timeFormat24": "24 heures", + "@timeFormat24": {}, + "timeFormatDevice": "Paramètre de l'appareil", + "@timeFormatDevice": {}, + "showSecondsSetting": "Montrez les secondes", + "@showSecondsSetting": {}, + "timePickerSetting": "Réglage de l’heure", + "@timePickerSetting": {}, + "pickerDial": "Cadran", + "@pickerDial": {}, + "pickerInput": "Clavier", + "@pickerInput": {}, + "durationPickerSetting": "Sélection de la durée", + "@durationPickerSetting": {}, + "autoStartSettingDescription": "Certains appareils nécessitent que le démarrage automatique ne soit activé pour que les alarmes sonnent malgré que l'application ne soit fermée", + "@autoStartSettingDescription": {}, + "pickerRings": "Sonneries", + "@pickerRings": {}, + "swipeActionSetting": "Action de glisser", + "@swipeActionSetting": {}, + "pickerSpinner": "Tourniquet", + "@pickerSpinner": {}, + "swipActionSwitchTabs": "Changer d'onglet", + "@swipActionSwitchTabs": {}, + "swipeActionSwitchTabsDescription": "Balayer entre les onglets", + "@swipeActionSwitchTabsDescription": {}, + "swipeActionCardActionDescription": "Balayer à gauche ou à droite pour effectuer une action", + "@swipeActionCardActionDescription": {}, + "melodiesSetting": "Mélodies", + "@melodiesSetting": {}, + "tagsSetting": "Étiquettes", + "@tagsSetting": {}, + "vendorSetting": "Paramètre du vendeur", + "@vendorSetting": {}, + "vendorSettingDescription": "Désactiver manuellement les optimisations spécifiques au vendeur", + "@vendorSettingDescription": {}, + "batteryOptimizationSetting": "Désactiver l'optimisation de la batterie", + "@batteryOptimizationSetting": {}, + "batteryOptimizationSettingDescription": "Désactiver l'optimisation de la batterie pour cette application afin d'éviter que l'alarme ne soit retardée", + "@batteryOptimizationSettingDescription": {}, + "allowNotificationSettingDescription": "Autoriser les notifications sur l'écran de verrouillage pour les alarmes et le chronomètre", + "@allowNotificationSettingDescription": {}, + "allowNotificationSetting": "Autoriser les notifications", + "@allowNotificationSetting": {}, + "autoStartSetting": "Démarrage automatique", + "@autoStartSetting": {}, + "animationSettingGroup": "Animations", + "@animationSettingGroup": {}, + "defaultLabel": "Défaut", + "@defaultLabel": {}, + "versionLabel": "Version", + "@versionLabel": {}, + "licenseLabel": "Licence", + "@licenseLabel": {}, + "emailLabel": "Adresse mail", + "@emailLabel": {}, + "viewOnGithubLabel": "Afficher sur GitHub", + "@viewOnGithubLabel": {}, + "scheduleTypeDate": "Sur des dates spécifiques", + "@scheduleTypeDate": {}, + "soundAndVibrationSettingGroup": "Son et Vibration", + "@soundAndVibrationSettingGroup": {}, + "audioChannelAlarm": "Alarme", + "@audioChannelAlarm": {}, + "audioChannelNotification": "Notification", + "@audioChannelNotification": {}, + "mathEasyDifficulty": "Facile (X + Y)", + "@mathEasyDifficulty": {}, + "mathMediumDifficulty": "Intermédiaire (X × Y)", + "@mathMediumDifficulty": {}, + "mathHardDifficulty": "Difficile (X × Y + Z)", + "@mathHardDifficulty": {}, + "mathVeryHardDifficulty": "Très difficile (X × Y × Z)", + "@mathVeryHardDifficulty": {}, + "numberOfProblemsSetting": "Nombre de problèmes", + "@numberOfProblemsSetting": {}, + "tomorrowFilter": "Demain", + "@tomorrowFilter": {}, + "stateFilterGroup": "État", + "@stateFilterGroup": {}, + "timeOfDayAsc": "Les heures les plus tôt en premier", + "@timeOfDayAsc": {}, + "disableAllFilteredAlarmsAction": "Désactiver toutes les alarmes filtrées", + "@disableAllFilteredAlarmsAction": {}, + "skipAllFilteredAlarmsAction": "Ignorer toutes les alarmes filtrées", + "@skipAllFilteredAlarmsAction": {}, + "filtersSettingGroup": "Filtres", + "@filtersSettingGroup": {}, + "showFiltersSetting": "Montrer les filtres", + "@showFiltersSetting": {}, + "timerDefaultSettingGroupDescription": "Définir des valeurs par défaut pour les nouveaux minuteurs", + "@timerDefaultSettingGroupDescription": {}, + "stopwatchTimeFormatSettingGroup": "Format de l'heure", + "@stopwatchTimeFormatSettingGroup": {}, + "stopwatchShowMillisecondsSetting": "Afficher les millisecondes", + "@stopwatchShowMillisecondsSetting": {}, + "swipActionCardAction": "Actions des cartes", + "@swipActionCardAction": {}, + "animationSpeedSetting": "Vitesse de l'animation", + "@animationSpeedSetting": {}, + "extraAnimationSetting": "Animations supplémentaires", + "@extraAnimationSetting": {}, + "nameField": "Nom", + "@nameField": {}, + "previewLabel": "Aperçu", + "@previewLabel": {}, + "colorSetting": "Couleur", + "@colorSetting": {}, + "textColorSetting": "Texte", + "@textColorSetting": {}, + "colorSchemeNamePlaceholder": "Palette de couleurs", + "@colorSchemeNamePlaceholder": {}, + "colorSchemeBackgroundSettingGroup": "Arrière-plan", + "@colorSchemeBackgroundSettingGroup": {}, + "colorSchemeAccentSettingGroup": "Couleur d'accentuation", + "@colorSchemeAccentSettingGroup": {}, + "colorSchemeErrorSettingGroup": "Erreur", + "@colorSchemeErrorSettingGroup": {}, + "colorSchemeCardSettingGroup": "Carte", + "@colorSchemeCardSettingGroup": {}, + "colorSchemeOutlineSettingGroup": "Contour", + "@colorSchemeOutlineSettingGroup": {}, + "colorSchemeShadowSettingGroup": "Ombre", + "@colorSchemeShadowSettingGroup": {}, + "colorSchemeUseAccentAsOutlineSetting": "Utiliser la couleur accentuée comme contour", + "@colorSchemeUseAccentAsOutlineSetting": {}, + "colorSchemeUseAccentAsShadowSetting": "Utiliser la couleur accentuée comme ombre", + "@colorSchemeUseAccentAsShadowSetting": {}, + "styleThemeNamePlaceholder": "Style de thème", + "@styleThemeNamePlaceholder": {}, + "styleThemeShadowSettingGroup": "Ombre", + "@styleThemeShadowSettingGroup": {}, + "styleThemeShapeSettingGroup": "Forme", + "@styleThemeShapeSettingGroup": {}, + "styleThemeRadiusSetting": "Arrondi des angles", + "@styleThemeRadiusSetting": {}, + "styleThemeOpacitySetting": "Opacité", + "@styleThemeOpacitySetting": {}, + "styleThemeBlurSetting": "Flou", + "@styleThemeBlurSetting": {}, + "styleThemeSpreadSetting": "Réglage de propagation du style de thème", + "@styleThemeSpreadSetting": {}, + "styleThemeOutlineSettingGroup": "Contour", + "@styleThemeOutlineSettingGroup": {}, + "styleThemeOutlineWidthSetting": "Largeur", + "@styleThemeOutlineWidthSetting": {}, + "showIstantAlarmButtonSetting": "Afficher le bouton d'alarme instantanée", + "@showIstantAlarmButtonSetting": {}, + "showIstantTimerButtonSetting": "Afficher le bouton de minuterie instantanée", + "@showIstantTimerButtonSetting": {}, + "logsSettingGroup": "Journaux", + "@logsSettingGroup": {}, + "alarmLogSetting": "Logs des alarmes", + "@alarmLogSetting": {}, + "resetButton": "Remettre à zéro", + "@resetButton": {}, + "cardLabel": "Carte", + "@cardLabel": {}, + "accentLabel": "Accent", + "@accentLabel": {}, + "errorLabel": "Erreur", + "@errorLabel": {}, + "materialBrightnessSystem": "Système", + "@materialBrightnessSystem": {}, + "materialBrightnessLight": "Lumière", + "@materialBrightnessLight": {}, + "materialBrightnessDark": "Sombre", + "@materialBrightnessDark": {}, + "accentColorSetting": "Couleur accentuée", + "@accentColorSetting": {}, + "alarmWeekdaysSetting": "Jours de la semaine", + "@alarmWeekdaysSetting": {}, + "mondayLetter": "L", + "@mondayLetter": {}, + "tuesdayLetter": "M", + "@tuesdayLetter": {}, + "wednesdayLetter": "Me", + "@wednesdayLetter": {}, + "thursdayLetter": "J", + "@thursdayLetter": {}, + "fridayLetter": "V", + "@fridayLetter": {}, + "saturdayLetter": "S", + "@saturdayLetter": {}, + "sundayLetter": "D", + "@sundayLetter": {}, + "alarmDatesSetting": "Dates", + "@alarmDatesSetting": {}, + "alarmRangeSetting": "Intervalle de dates", + "@alarmRangeSetting": {}, + "alarmIntervalSetting": "Interval", + "@alarmIntervalSetting": {}, + "alarmIntervalDaily": "Tous les jours", + "@alarmIntervalDaily": {}, + "alarmIntervalWeekly": "Chaque semaine", + "@alarmIntervalWeekly": {}, + "alarmDeleteAfterRingingSetting": "Supprimer après avoir été arrêté", + "@alarmDeleteAfterRingingSetting": {}, + "alarmDeleteAfterFinishingSetting": "Supprimer après avoir terminé", + "@alarmDeleteAfterFinishingSetting": {}, + "yesButton": "Oui", + "@yesButton": {}, + "cannotDisableAlarmWhileSnoozedSnackbar": "Impossible de désactiver l'alarme tant qu'elle est en mode répétition", + "@cannotDisableAlarmWhileSnoozedSnackbar": {}, + "completedFilter": "Terminée", + "@completedFilter": {}, + "sortGroup": "Trier", + "@sortGroup": {}, + "timePickerModeButton": "Mode", + "@timePickerModeButton": {}, + "audioChannelRingtone": "Sonnerie", + "@audioChannelRingtone": {}, + "timeToFullVolumeSetting": "Temps jusqu'au volume maximal", + "@timeToFullVolumeSetting": {}, + "maxSnoozesSetting": "Nombre maximum de répétitions", + "@maxSnoozesSetting": {}, + "snoozePreventDeletionSetting": "Empêcher la suppression", + "@snoozePreventDeletionSetting": {}, + "nameAsc": "Noms A-z", + "@nameAsc": {}, + "retypeNumberChars": "Nombre de charactères", + "@retypeNumberChars": {}, + "retypeIncludeNumSetting": "Inclure des chiffres", + "@retypeIncludeNumSetting": {}, + "retypeLowercaseSetting": "Inclure des lettres en minuscules", + "@retypeLowercaseSetting": {}, + "sequenceLengthSetting": "Longueur de la séquence", + "@sequenceLengthSetting": {}, + "sequenceGridSizeSetting": "Taille de la grille", + "@sequenceGridSizeSetting": {}, + "saveReminderAlert": "Voulez-vous quitter le menu sans sauvegarder ?", + "@saveReminderAlert": {}, + "noButton": "Non", + "@noButton": {}, + "noAlarmMessage": "Aucune alarme", + "@noAlarmMessage": {}, + "noTimerMessage": "Aucun minuteur", + "@noTimerMessage": {}, + "noStopwatchMessage": "Aucun chronomètre", + "@noStopwatchMessage": {}, + "noTaskMessage": "Aucune tâche", + "@noTaskMessage": {}, + "noPresetsMessage": "Aucun préréglage", + "@noPresetsMessage": {}, + "noLogsMessage": "Aucun log d'alarme", + "@noLogsMessage": {}, + "deleteButton": "Supprimer", + "@deleteButton": {}, + "duplicateButton": "Dupliquer", + "@duplicateButton": {}, + "skipAlarmButton": "Ignorer l'alarme suivante", + "@skipAlarmButton": {}, + "allFilter": "Tous", + "@allFilter": {}, + "dateFilterGroup": "Date", + "@dateFilterGroup": {}, + "logTypeFilterGroup": "Type", + "@logTypeFilterGroup": {}, + "todayFilter": "Aujourd'hui", + "@todayFilter": {}, + "createdDateFilterGroup": "Date de création", + "@createdDateFilterGroup": {}, + "activeFilter": "Active", + "@activeFilter": {}, + "inactiveFilter": "Inactif", + "@inactiveFilter": {}, + "snoozedFilter": "Ignorée", + "@snoozedFilter": {}, + "disabledFilter": "Désactiver", + "@disabledFilter": {}, + "runningTimerFilter": "En cours", + "@runningTimerFilter": {}, + "pausedTimerFilter": "En pause", + "@pausedTimerFilter": {}, + "stoppedTimerFilter": "Arrêté", + "@stoppedTimerFilter": {}, + "remainingTimeDesc": "Temps restant le plus court", + "@remainingTimeDesc": {}, + "remainingTimeAsc": "Temps restant le plus long", + "@remainingTimeAsc": {}, + "durationAsc": "Le plus court", + "@durationAsc": {}, + "durationDesc": "Le plus long", + "@durationDesc": {}, + "timeOfDayDesc": "Les heures les plus tard en premier", + "@timeOfDayDesc": {}, + "filterActions": "Trier les actions", + "@filterActions": {}, + "clearFiltersAction": "Effacer tous les filtres", + "@clearFiltersAction": {}, + "enableAllFilteredAlarmsAction": "Activer toutes les alarmes filtrées", + "@enableAllFilteredAlarmsAction": {}, + "packageNameLabel": "Nom du package", + "@packageNameLabel": {}, + "cancelSkipAllFilteredAlarmsAction": "Annuler d'ignorer toutes les alarmes filtrées", + "@cancelSkipAllFilteredAlarmsAction": {}, + "deleteAllFilteredAction": "Supprimer toutes les alarmes filtrées", + "@deleteAllFilteredAction": {}, + "defaultSettingGroup": "Paramètres par défaut", + "@defaultSettingGroup": {}, + "alarmsDefaultSettingGroupDescription": "Définir des valeurs par défaut pour les nouvelles alarmes", + "@alarmsDefaultSettingGroupDescription": {}, + "notificationsSettingGroup": "Notifications", + "@notificationsSettingGroup": {}, + "showUpcomingAlarmNotificationSetting": "Afficher les notifications des prochaines alarmes", + "@showUpcomingAlarmNotificationSetting": {}, + "upcomingLeadTimeSetting": "Temps avant l'alarme pour afficher une notification de rappel", + "@upcomingLeadTimeSetting": {}, + "showSnoozeNotificationSetting": "Afficher une notification lorsque l'alarme est repoussée", + "@showSnoozeNotificationSetting": {}, + "presetsSetting": "Préréglages", + "@presetsSetting": {}, + "newPresetPlaceholder": "Nouveau préréglage", + "@newPresetPlaceholder": {}, + "dismissActionSetting": "Type d'action pour arrêter l'alarme", + "@dismissActionSetting": {}, + "dismissActionSlide": "Glisser", + "@dismissActionSlide": {}, + "dismissActionButtons": "Boutons", + "@dismissActionButtons": {}, + "dismissActionAreaButtons": "Boutons larges", + "@dismissActionAreaButtons": {}, + "comparisonLapBarsSettingGroup": "Comparaison des tours", + "@comparisonLapBarsSettingGroup": {}, + "showPreviousLapSetting": "Afficher le tour précédent", + "@showPreviousLapSetting": {}, + "showFastestLapSetting": "Afficher le tour le plus rapide", + "@showFastestLapSetting": {}, + "showAverageLapSetting": "Afficher le tour moyen", + "@showAverageLapSetting": {}, + "showSlowestLapSetting": "Afficher le tour le plus lent", + "@showSlowestLapSetting": {}, + "leftHandedSetting": "Mode gaucher", + "@leftHandedSetting": {}, + "exportSettingsSetting": "Exporter", + "@exportSettingsSetting": {}, + "exportSettingsSettingDescription": "Exporter les paramètres vers un fichier local", + "@exportSettingsSettingDescription": {}, + "importSettingsSetting": "Importer", + "@importSettingsSetting": {}, + "importSettingsSettingDescription": "Importer les paramètres à partir d'un fichier local", + "@importSettingsSettingDescription": {}, + "addLengthSetting": "Ajouter du temps supplémentaire", + "@addLengthSetting": {}, + "audioChannelMedia": "Média", + "@audioChannelMedia": {}, + "cancelSkipAlarmButton": "Annuler", + "@cancelSkipAlarmButton": {}, + "dismissAlarmButton": "Rejeter", + "@dismissAlarmButton": {}, + "scheduleDateFilterGroup": "Date prévue", + "@scheduleDateFilterGroup": {}, + "showSortSetting": "Afficher le tri", + "@showSortSetting": {}, + "showNotificationSetting": "Afficher une notification", + "@showNotificationSetting": {}, + "sameTime": "En même temps", + "@sameTime": {}, + "searchCityPlaceholder": "Rechercher une ville", + "@searchCityPlaceholder": {}, + "relativeTime": "{hours}h {relative, select, ahead{d’avance} behind{de retard} other{Other}}", + "@relativeTime": {}, + "cityAlreadyInFavorites": "Cette ville est déjà dans vos favoris", + "@cityAlreadyInFavorites": {}, + "durationPickerTitle": "Définir la durée", + "@durationPickerTitle": {}, + "editButton": "Modifier", + "@editButton": {}, + "noLapsMessage": "Pas de temps au tour", + "@noLapsMessage": {}, + "elapsedTime": "Temps écoulé", + "@elapsedTime": {}, + "mondayFull": "Lundi", + "@mondayFull": {}, + "fridayFull": "Vendredi", + "@fridayFull": {}, + "saturdayFull": "Samedi", + "@saturdayFull": {}, + "sundayFull": "Dimanche", + "@sundayFull": {}, + "mondayShort": "Lun", + "@mondayShort": {}, + "tuesdayShort": "Mar", + "@tuesdayShort": {}, + "wednesdayShort": "Mer", + "@wednesdayShort": {}, + "thursdayShort": "Jeu", + "@thursdayShort": {}, + "fridayShort": "Ven", + "@fridayShort": {}, + "saturdayShort": "Sam", + "@saturdayShort": {}, + "sundayShort": "Dim", + "@sundayShort": {}, + "nameDesc": "Noms Z-a", + "@nameDesc": {}, + "alarmDescriptionWeekly": "Tous les {days}", + "@alarmDescriptionWeekly": {}, + "tuesdayFull": "Mardi", + "@tuesdayFull": {}, + "wednesdayFull": "Mercredi", + "@wednesdayFull": {}, + "thursdayFull": "Jeudi", + "@thursdayFull": {}, + "maxLogsSetting": "Nombres de journaux", + "@maxLogsSetting": {}, + "styleThemeElevationSetting": "Élévation", + "@styleThemeElevationSetting": {}, + "searchSettingPlaceholder": "Rechercher", + "@searchSettingPlaceholder": {}, + "openSourceLicensesSetting": "Licence open source", + "@openSourceLicensesSetting": {}, + "contributorsSetting": "Contributeurs", + "@contributorsSetting": {}, + "donorsSetting": "Donateurs", + "@donorsSetting": {}, + "donateButton": "Donner", + "@donateButton": {}, + "donorsDescription": "Nos généreux patreons", + "@donorsDescription": {}, + "contributorsDescription": "Personnes qui ont rendu cette app possible", + "@contributorsDescription": {}, + "donateDescription": "Donner pour supporter le développement de l’application", + "@donateDescription": {} +} diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb new file mode 100644 index 00000000..4bc72fa2 --- /dev/null +++ b/lib/l10n/app_it.arb @@ -0,0 +1,66 @@ +{ + "languageSetting": "Lingua", + "@languageSetting": {}, + "dateFormatSetting": "Formato data", + "@dateFormatSetting": {}, + "timeFormatSetting": "Formato ora", + "@timeFormatSetting": {}, + "timeFormat12": "12 ore", + "@timeFormat12": {}, + "timeFormat24": "24 ore", + "@timeFormat24": {}, + "timeFormatDevice": "Impostazioni dispositivo", + "@timeFormatDevice": {}, + "showSecondsSetting": "Mostra secondi", + "@showSecondsSetting": {}, + "clockTitle": "Orologio", + "@clockTitle": { + "description": "Title of the clock screen" + }, + "alarmTitle": "Sveglia", + "@alarmTitle": { + "description": "Title of the alarm screen" + }, + "timerTitle": "Timer", + "@timerTitle": { + "description": "Title of the timer screen" + }, + "stopwatchTitle": "Cronometro", + "@stopwatchTitle": { + "description": "Title of the stopwatch screen" + }, + "generalSettingGroup": "Generali", + "@generalSettingGroup": {}, + "system": "Sistema", + "@system": {}, + "melodiesSetting": "Melodie", + "@melodiesSetting": {}, + "appearanceSettingGroup": "Aspetto", + "@appearanceSettingGroup": {}, + "appearanceSettingGroupDescription": "Cambia tema, colori e layout", + "@appearanceSettingGroupDescription": {}, + "timePickerSetting": "Imposta ora", + "@timePickerSetting": {}, + "pickerInput": "Input", + "@pickerInput": {}, + "swipeActionSetting": "Azioni di scorrimento", + "@swipeActionSetting": {}, + "animationSettingGroup": "Animazioni", + "@animationSettingGroup": {}, + "animationSpeedSetting": "Velocità delle animazioni", + "@animationSpeedSetting": {}, + "extraAnimationSetting": "Animazioni aggiuntive", + "@extraAnimationSetting": {}, + "nameField": "Nome", + "@nameField": {}, + "colorSetting": "Colore", + "@colorSetting": {}, + "textColorSetting": "Testo", + "@textColorSetting": {}, + "colorSchemeNamePlaceholder": "Palette dei colori", + "@colorSchemeNamePlaceholder": {}, + "colorSchemeBackgroundSettingGroup": "Sfondo", + "@colorSchemeBackgroundSettingGroup": {}, + "colorSchemeErrorSettingGroup": "Errore", + "@colorSchemeErrorSettingGroup": {} +} diff --git a/lib/l10n/app_nb.arb b/lib/l10n/app_nb.arb new file mode 100644 index 00000000..630e16ed --- /dev/null +++ b/lib/l10n/app_nb.arb @@ -0,0 +1,82 @@ +{ + "timerTitle": "Tidsur", + "@timerTitle": { + "description": "Title of the timer screen" + }, + "colorsSettingGroup": "Farger", + "@colorsSettingGroup": {}, + "styleSettingGroup": "Stil", + "@styleSettingGroup": {}, + "stopwatchTitle": "Stoppeklokke", + "@stopwatchTitle": { + "description": "Title of the stopwatch screen" + }, + "generalSettingGroup": "Generelt", + "@generalSettingGroup": {}, + "appearanceSettingGroup": "Utseende", + "@appearanceSettingGroup": {}, + "accessibilitySettingGroup": "Tilgjengelighet", + "@accessibilitySettingGroup": {}, + "developerOptionsSettingGroup": "Utvikleralternativer", + "@developerOptionsSettingGroup": {}, + "aboutSettingGroup": "Om", + "@aboutSettingGroup": {}, + "clockSettingGroup": "Klokke", + "@clockSettingGroup": {}, + "timerSettingGroup": "Tidsur", + "@timerSettingGroup": {}, + "stopwatchSettingGroup": "Stoppeklokke", + "@stopwatchSettingGroup": {}, + "skipAlarmButton": "Hopp over neste alarm", + "@skipAlarmButton": {}, + "allFilter": "Alle", + "@allFilter": {}, + "todayFilter": "I dag", + "@todayFilter": {}, + "tomorrowFilter": "I morgen", + "@tomorrowFilter": {}, + "clockTitle": "Klokke", + "@clockTitle": { + "description": "Title of the clock screen" + }, + "materialBrightnessSetting": "Lysstyrke", + "@materialBrightnessSetting": {}, + "tasksSetting": "Gjøremål", + "@tasksSetting": {}, + "deleteButton": "Slett", + "@deleteButton": {}, + "alarmTitle": "Alarm", + "@alarmTitle": { + "description": "Title of the alarm screen" + }, + "overrideAccentSetting": "Overstyr kontrastfarge", + "@overrideAccentSetting": {}, + "settings": "Innstillinger", + "@settings": {}, + "selectTime": "Velg tid", + "@selectTime": {}, + "cancelButton": "Avbryt", + "@cancelButton": {}, + "customizeButton": "Tilpass", + "@customizeButton": {}, + "labelField": "Etikett", + "@labelField": {}, + "labelFieldPlaceholder": "Legg til etikett", + "@labelFieldPlaceholder": {}, + "vibrationSetting": "Vibrasjon", + "@vibrationSetting": {}, + "scheduleTypeField": "Type", + "@scheduleTypeField": {}, + "volumeSetting": "Lydstyrke", + "@volumeSetting": {}, + "scheduleTypeOnce": "Enkeltstående", + "@scheduleTypeOnce": {}, + "scheduleTypeDaily": "Daglig", + "@scheduleTypeDaily": {}, + "audioChannelSetting": "Lydkanal", + "@audioChannelSetting": {}, + "risingVolumeSetting": "Økende lydstyrke", + "@risingVolumeSetting": {}, + "snoozeLengthSetting": "Lengde", + "@snoozeLengthSetting": {} +} diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb new file mode 100644 index 00000000..c442eb66 --- /dev/null +++ b/lib/l10n/app_pl.arb @@ -0,0 +1,108 @@ +{ + "restoreSettingGroup": "Przywróć domyślne wartości", + "@restoreSettingGroup": {}, + "colorsSettingGroup": "Kolory", + "@colorsSettingGroup": {}, + "styleSettingGroup": "Styl", + "@styleSettingGroup": {}, + "useMaterialYouColorSetting": "Użyj Material You", + "@useMaterialYouColorSetting": {}, + "materialBrightnessSetting": "Jasność", + "@materialBrightnessSetting": {}, + "colorSchemeSetting": "Paleta kolorów", + "@colorSchemeSetting": {}, + "cancelButton": "Anuluj", + "@cancelButton": {}, + "customizeButton": "Dostosuj", + "@customizeButton": {}, + "yesButton": "Tak", + "@yesButton": {}, + "stopwatchPrevious": "Poprzedni", + "@stopwatchPrevious": {}, + "stopwatchFastest": "Najszybszy", + "@stopwatchFastest": {}, + "stopwatchSlowest": "Najwolniejszy", + "@stopwatchSlowest": {}, + "clockTitle": "Zegar", + "@clockTitle": { + "description": "Title of the clock screen" + }, + "alarmTitle": "Alarm", + "@alarmTitle": { + "description": "Title of the alarm screen" + }, + "aboutSettingGroup": "O aplikacji", + "@aboutSettingGroup": {}, + "overrideAccentSetting": "Nadpisz kolor akcentu", + "@overrideAccentSetting": {}, + "timerTitle": "Czasomierz", + "@timerTitle": { + "description": "Title of the timer screen" + }, + "useMaterialStyleSetting": "Użyj stylu Material", + "@useMaterialStyleSetting": {}, + "generalSettingGroup": "Ogólne", + "@generalSettingGroup": {}, + "appearanceSettingGroup": "Wygląd", + "@appearanceSettingGroup": {}, + "accessibilitySettingGroup": "Dostępność", + "@accessibilitySettingGroup": {}, + "backupSettingGroup": "Kopia zapasowa", + "@backupSettingGroup": {}, + "developerOptionsSettingGroup": "Opcje programistyczne", + "@developerOptionsSettingGroup": {}, + "styleThemeSetting": "Motyw", + "@styleThemeSetting": {}, + "clockSettingGroup": "Zegar", + "@clockSettingGroup": {}, + "labelField": "Etykieta", + "@labelField": {}, + "alarmScheduleSettingGroup": "Kolejka", + "@alarmScheduleSettingGroup": {}, + "settingGroupMore": "Więcej", + "@settingGroupMore": {}, + "vibrationSetting": "Wibracje", + "@vibrationSetting": {}, + "snoozeEnableSetting": "Włączono", + "@snoozeEnableSetting": {}, + "tasksSetting": "Zadania", + "@tasksSetting": {}, + "stopwatchAverage": "Średnia", + "@stopwatchAverage": {}, + "scheduleTypeField": "Typ", + "@scheduleTypeField": {}, + "scheduleTypeOnce": "Raz", + "@scheduleTypeOnce": {}, + "melodySetting": "Melodia", + "@melodySetting": {}, + "volumeSetting": "Głośność", + "@volumeSetting": {}, + "snoozeLengthSetting": "Długość", + "@snoozeLengthSetting": {}, + "noButton": "Nie", + "@noButton": {}, + "timerSettingGroup": "Czasomierz", + "@timerSettingGroup": {}, + "scheduleTypeDaily": "Codziennie", + "@scheduleTypeDaily": {}, + "settings": "Ustawienia", + "@settings": {}, + "selectTime": "Wybierz czas", + "@selectTime": {}, + "mathTaskDifficultySetting": "Poziom trudności", + "@mathTaskDifficultySetting": {}, + "deleteButton": "Usuń", + "@deleteButton": {}, + "duplicateButton": "Duplikuj", + "@duplicateButton": {}, + "allFilter": "Wszystko", + "@allFilter": {}, + "todayFilter": "Dzisiaj", + "@todayFilter": {}, + "tomorrowFilter": "Jutro", + "@tomorrowFilter": {}, + "disabledFilter": "Wyłączono", + "@disabledFilter": {}, + "completedFilter": "Zakończone", + "@completedFilter": {} +} diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb new file mode 100644 index 00000000..a5798f63 --- /dev/null +++ b/lib/l10n/app_pt.arb @@ -0,0 +1,470 @@ +{ + "alarmTitle": "Alarme", + "@alarmTitle": { + "description": "Title of the alarm screen" + }, + "stopwatchTitle": "Cronómetro", + "@stopwatchTitle": { + "description": "Title of the stopwatch screen" + }, + "clockTitle": "Relógio", + "@clockTitle": { + "description": "Title of the clock screen" + }, + "timerTitle": "Temporizador", + "@timerTitle": { + "description": "Title of the timer screen" + }, + "backupSettingGroup": "Definições", + "@backupSettingGroup": {}, + "developerOptionsSettingGroup": "Opções de programador", + "@developerOptionsSettingGroup": {}, + "aboutSettingGroup": "Acerca", + "@aboutSettingGroup": {}, + "restoreSettingGroup": "Repor valores padrão", + "@restoreSettingGroup": {}, + "displaySettingGroup": "Exibição", + "@displaySettingGroup": {}, + "colorsSettingGroup": "Cores", + "@colorsSettingGroup": {}, + "styleSettingGroup": "Estilo", + "@styleSettingGroup": {}, + "useMaterialYouColorSetting": "Material You", + "@useMaterialYouColorSetting": {}, + "materialBrightnessSetting": "Brilho", + "@materialBrightnessSetting": {}, + "overrideAccentSetting": "Substituir cor de destaque", + "@overrideAccentSetting": {}, + "useMaterialStyleSetting": "Estilo Material You", + "@useMaterialStyleSetting": {}, + "styleThemeSetting": "Estilo do tema", + "@styleThemeSetting": {}, + "systemDarkModeSetting": "Modo escuro", + "@systemDarkModeSetting": {}, + "colorSchemeSetting": "Esquema de cores", + "@colorSchemeSetting": {}, + "customizeButton": "Personalizar", + "@customizeButton": {}, + "saveButton": "Guardar", + "@saveButton": {}, + "labelField": "Etiqueta", + "@labelField": {}, + "labelFieldPlaceholder": "Adicionar etiqueta", + "@labelFieldPlaceholder": {}, + "alarmScheduleSettingGroup": "Agendar", + "@alarmScheduleSettingGroup": {}, + "scheduleTypeField": "Tipo", + "@scheduleTypeField": {}, + "scheduleTypeOnce": "Uma vez", + "@scheduleTypeOnce": {}, + "scheduleTypeDaily": "Diariamente", + "@scheduleTypeDaily": {}, + "scheduleTypeRange": "Intervalo de tempo", + "@scheduleTypeRange": {}, + "reliabilitySettingGroup": "Fiabilidade", + "@reliabilitySettingGroup": {}, + "generalSettingGroupDescription": "Definições globais da aplicação", + "@generalSettingGroupDescription": {}, + "appearanceSettingGroupDescription": "Temas, cores e esquemas", + "@appearanceSettingGroupDescription": {}, + "backupSettingGroupDescription": "Exportar ou importar definições", + "@backupSettingGroupDescription": {}, + "selectTime": "Definir hora", + "@selectTime": {}, + "scheduleTypeOnceDescription": "Será ativado na próxima ocorrência da hora", + "@scheduleTypeOnceDescription": {}, + "settingGroupMore": "Mais", + "@settingGroupMore": {}, + "melodySetting": "Melodia", + "@melodySetting": {}, + "vibrationSetting": "Vibração", + "@vibrationSetting": {}, + "audioChannelSetting": "Canal de áudio", + "@audioChannelSetting": {}, + "volumeSetting": "Volume", + "@volumeSetting": {}, + "risingVolumeSetting": "Aumento gradual", + "@risingVolumeSetting": {}, + "snoozeSettingGroup": "Snooze", + "@snoozeSettingGroup": {}, + "snoozeEnableSetting": "Ligado", + "@snoozeEnableSetting": {}, + "settings": "Definições", + "@settings": {}, + "tasksSetting": "Tarefas", + "@tasksSetting": {}, + "snoozeLengthSetting": "Duração", + "@snoozeLengthSetting": {}, + "snoozePreventDisablingSetting": "Impedir desativação", + "@snoozePreventDisablingSetting": {}, + "chooseTaskTitle": "Escolha o tipo de tarefa", + "@chooseTaskTitle": {}, + "mathTask": "Matemática", + "@mathTask": {}, + "retypeTask": "Escrever texto", + "@retypeTask": {}, + "sequenceTask": "Sequência", + "@sequenceTask": {}, + "taskTryButton": "Testar", + "@taskTryButton": {}, + "mathTaskDifficultySetting": "Dificuldade", + "@mathTaskDifficultySetting": {}, + "retypeNumberChars": "Número de caracteres", + "@retypeNumberChars": {}, + "retypeIncludeNumSetting": "Incluir números", + "@retypeIncludeNumSetting": {}, + "retypeLowercaseSetting": "Incluir minúsculas", + "@retypeLowercaseSetting": {}, + "whileSnoozedSettingGroup": "Em snooze", + "@whileSnoozedSettingGroup": {}, + "soundSettingGroup": "Som", + "@soundSettingGroup": {}, + "generalSettingGroup": "Geral", + "@generalSettingGroup": {}, + "appearanceSettingGroup": "Aparência", + "@appearanceSettingGroup": {}, + "accessibilitySettingGroup": "Acessibilidade", + "@accessibilitySettingGroup": {}, + "darkColorSchemeSetting": "Esquema escuro", + "@darkColorSchemeSetting": {}, + "clockSettingGroup": "Relógio", + "@clockSettingGroup": {}, + "timerSettingGroup": "Temporizador", + "@timerSettingGroup": {}, + "stopwatchSettingGroup": "Cronómetro", + "@stopwatchSettingGroup": {}, + "cancelButton": "Cancelar", + "@cancelButton": {}, + "sequenceLengthSetting": "Tamanho da sequência", + "@sequenceLengthSetting": {}, + "sequenceGridSizeSetting": "Tamanho da grelha", + "@sequenceGridSizeSetting": {}, + "saveReminderAlert": "Deseja sair sem guardar as alterações?", + "@saveReminderAlert": {}, + "scheduleTypeDailyDescription": "Será ativado todos os dias", + "@scheduleTypeDailyDescription": {}, + "yesButton": "Sim", + "@yesButton": {}, + "deleteButton": "Eliminar", + "@deleteButton": {}, + "noButton": "Não", + "@noButton": {}, + "duplicateButton": "Duplicar", + "@duplicateButton": {}, + "skipAlarmButton": "Ignorar próximo alarme", + "@skipAlarmButton": {}, + "allFilter": "Tudo", + "@allFilter": {}, + "todayFilter": "Hoje", + "@todayFilter": {}, + "tomorrowFilter": "Amanhã", + "@tomorrowFilter": {}, + "snoozedFilter": "Snoozed", + "@snoozedFilter": {}, + "disabledFilter": "Desativado", + "@disabledFilter": {}, + "completedFilter": "Terminado", + "@completedFilter": {}, + "scheduleTypeWeek": "Em dias específicos", + "@scheduleTypeWeek": {}, + "scheduleTypeWeekDescription": "Será ativado em dias específicos", + "@scheduleTypeWeekDescription": {}, + "scheduleTypeDateDescription": "Será ativado nas datas especificadas", + "@scheduleTypeDateDescription": {}, + "scheduleTypeRangeDescription": "Será ativado durante o intervalo especificado", + "@scheduleTypeRangeDescription": {}, + "noItemMessage": "Ainda não adicionou {items}", + "@noItemMessage": {}, + "skippingDescriptionSuffix": "(ignorar próxima ocorrência)", + "@skippingDescriptionSuffix": {}, + "alarmDescriptionSnooze": "Silenciado até {date}", + "@alarmDescriptionSnooze": {}, + "alarmDescriptionFinished": "Não existem mais alarmes", + "@alarmDescriptionFinished": {}, + "alarmDescriptionNotScheduled": "Não agendado", + "@alarmDescriptionNotScheduled": {}, + "alarmDescriptionToday": "Apenas hoje", + "@alarmDescriptionToday": {}, + "alarmDescriptionTomorrow": "Apenas amanhã", + "@alarmDescriptionTomorrow": {}, + "alarmDescriptionEveryDay": "Todos os dias", + "@alarmDescriptionEveryDay": {}, + "alarmDescriptionWeekend": "Todas as semanas", + "@alarmDescriptionWeekend": {}, + "stopwatchPrevious": "Anterior", + "@stopwatchPrevious": {}, + "alarmDescriptionWeekday": "Todos os dias da semana", + "@alarmDescriptionWeekday": {}, + "stopwatchFastest": "Mais rápida", + "@stopwatchFastest": {}, + "alarmDescriptionDays": "{days}", + "@alarmDescriptionDays": {}, + "alarmDescriptionRange": "{interval, select, daily{Diariamente} weekly{Semanalmente} other{Other}} entre {startDate} e {endDate}", + "@alarmDescriptionRange": {}, + "stopwatchSlowest": "Mais lenta", + "@stopwatchSlowest": {}, + "alarmDescriptionDates": "Em {date}{count, plural, =0{} =1{ e mais 1 data} other{ e mais {count} datas}}", + "@alarmDescriptionDates": {}, + "stopwatchAverage": "Média", + "@stopwatchAverage": {}, + "pickerSpinner": "Spinner", + "@pickerSpinner": {}, + "durationPickerSetting": "Seletor de duração", + "@durationPickerSetting": {}, + "pickerRings": "Anéis", + "@pickerRings": {}, + "swipeActionSetting": "Ação de deslize", + "@swipeActionSetting": {}, + "system": "Sistema", + "@system": {}, + "languageSetting": "Idioma", + "@languageSetting": {}, + "dateFormatSetting": "Formato da data", + "@dateFormatSetting": {}, + "timeFormatSetting": "Formato da hora", + "@timeFormatSetting": {}, + "timeFormat12": "12 horas", + "@timeFormat12": {}, + "timeFormat24": "24 horas", + "@timeFormat24": {}, + "timeFormatDevice": "Definições do dispositivo", + "@timeFormatDevice": {}, + "showSecondsSetting": "Mostrar segundos", + "@showSecondsSetting": {}, + "timePickerSetting": "Seletor de hora", + "@timePickerSetting": {}, + "pickerDial": "Marcador", + "@pickerDial": {}, + "pickerInput": "Introdução", + "@pickerInput": {}, + "swipActionCardAction": "Ações em cartões", + "@swipActionCardAction": {}, + "swipeActionCardActionDescription": "Deslizar à direita/esquerda no cartão para executar ações", + "@swipeActionCardActionDescription": {}, + "swipActionSwitchTabs": "Troca de separadores", + "@swipActionSwitchTabs": {}, + "swipeActionSwitchTabsDescription": "Deslizar entre separadores", + "@swipeActionSwitchTabsDescription": {}, + "melodiesSetting": "Melodias", + "@melodiesSetting": {}, + "tagsSetting": "Etiquetas", + "@tagsSetting": {}, + "vendorSetting": "Definição do fabricante", + "@vendorSetting": {}, + "batteryOptimizationSetting": "Desativar otimização de bateria", + "@batteryOptimizationSetting": {}, + "colorSetting": "Cor", + "@colorSetting": {}, + "textColorSetting": "Texto", + "@textColorSetting": {}, + "styleThemeShapeSettingGroup": "Forma", + "@styleThemeShapeSettingGroup": {}, + "styleThemeElevationSetting": "Elevação", + "@styleThemeElevationSetting": {}, + "styleThemeShadowSettingGroup": "Sombra", + "@styleThemeShadowSettingGroup": {}, + "autoStartSetting": "Arranque automático", + "@autoStartSetting": {}, + "vendorSettingDescription": "Desativar otimizações definidas pelo fabricante", + "@vendorSettingDescription": {}, + "batteryOptimizationSettingDescription": "Desativar otimização de bateria para permitir um correto funcionamento da aplicação", + "@batteryOptimizationSettingDescription": {}, + "allowNotificationSettingDescription": "Permitir notificações no ecrã de bloqueio", + "@allowNotificationSettingDescription": {}, + "autoStartSettingDescription": "Em alguns dispositivos, tem que ativar o arranque automático para ativar os alarmes quando a aplicação está fechada", + "@autoStartSettingDescription": {}, + "allowNotificationSetting": "Permitir notificações", + "@allowNotificationSetting": {}, + "extraAnimationSetting": "Animações adicionais", + "@extraAnimationSetting": {}, + "animationSettingGroup": "Animações", + "@animationSettingGroup": {}, + "animationSpeedSetting": "Velocidade das animações", + "@animationSpeedSetting": {}, + "nameField": "Nome", + "@nameField": {}, + "colorSchemeNamePlaceholder": "Esquema de cores", + "@colorSchemeNamePlaceholder": {}, + "colorSchemeBackgroundSettingGroup": "Fundo", + "@colorSchemeBackgroundSettingGroup": {}, + "colorSchemeAccentSettingGroup": "Destaque", + "@colorSchemeAccentSettingGroup": {}, + "colorSchemeErrorSettingGroup": "Erro", + "@colorSchemeErrorSettingGroup": {}, + "colorSchemeCardSettingGroup": "Cartão", + "@colorSchemeCardSettingGroup": {}, + "colorSchemeOutlineSettingGroup": "Contorno", + "@colorSchemeOutlineSettingGroup": {}, + "colorSchemeShadowSettingGroup": "Sombra", + "@colorSchemeShadowSettingGroup": {}, + "colorSchemeUseAccentAsOutlineSetting": "Mesma cor para destaque e contorno", + "@colorSchemeUseAccentAsOutlineSetting": {}, + "colorSchemeUseAccentAsShadowSetting": "Mesma cor para destaque e sombra", + "@colorSchemeUseAccentAsShadowSetting": {}, + "styleThemeNamePlaceholder": "Estilo do tema", + "@styleThemeNamePlaceholder": {}, + "styleThemeRadiusSetting": "Curva dos cantos", + "@styleThemeRadiusSetting": {}, + "styleThemeOpacitySetting": "Opacidade", + "@styleThemeOpacitySetting": {}, + "styleThemeBlurSetting": "Desfoque", + "@styleThemeBlurSetting": {}, + "styleThemeOutlineSettingGroup": "Contorno", + "@styleThemeOutlineSettingGroup": {}, + "styleThemeOutlineWidthSetting": "Largura", + "@styleThemeOutlineWidthSetting": {}, + "showIstantAlarmButtonSetting": "Mostrar botão de alarme rápido", + "@showIstantAlarmButtonSetting": {}, + "showIstantTimerButtonSetting": "Mostrar botão de cronómetro rápido", + "@showIstantTimerButtonSetting": {}, + "logsSettingGroup": "Registos", + "@logsSettingGroup": {}, + "maxLogsSetting": "Máximo", + "@maxLogsSetting": {}, + "alarmLogSetting": "Registo de alarmes", + "@alarmLogSetting": {}, + "resetButton": "Repor", + "@resetButton": {}, + "previewLabel": "Antevisão", + "@previewLabel": {}, + "cardLabel": "Cartão", + "@cardLabel": {}, + "alarmDeleteAfterRingingSetting": "Eliminar após descartar", + "@alarmDeleteAfterRingingSetting": {}, + "alarmDeleteAfterFinishingSetting": "Eliminar após terminar", + "@alarmDeleteAfterFinishingSetting": {}, + "timePickerModeButton": "Modo", + "@timePickerModeButton": {}, + "scheduleTypeDate": "Em datas específicas", + "@scheduleTypeDate": {}, + "soundAndVibrationSettingGroup": "Sim e vibração", + "@soundAndVibrationSettingGroup": {}, + "timeToFullVolumeSetting": "Duração para volume total", + "@timeToFullVolumeSetting": {}, + "maxSnoozesSetting": "N.° máximo", + "@maxSnoozesSetting": {}, + "snoozePreventDeletionSetting": "Impedir eliminação", + "@snoozePreventDeletionSetting": {}, + "mathEasyDifficulty": "Fácil (X + Y)", + "@mathEasyDifficulty": {}, + "mathMediumDifficulty": "Média (X × Y)", + "@mathMediumDifficulty": {}, + "mathHardDifficulty": "Difícil (X × Y + Z)", + "@mathHardDifficulty": {}, + "mathVeryHardDifficulty": "Muito difícil (X × Y × Z)", + "@mathVeryHardDifficulty": {}, + "numberOfProblemsSetting": "Número de problemas", + "@numberOfProblemsSetting": {}, + "noAlarmMessage": "Não existem alarmes", + "@noAlarmMessage": {}, + "noTimerMessage": "Não existem temporizadores", + "@noTimerMessage": {}, + "noStopwatchMessage": "Não existem cronómetros", + "@noStopwatchMessage": {}, + "noTaskMessage": "Não existem tarefas", + "@noTaskMessage": {}, + "noPresetsMessage": "Não existem pré-ajustes", + "@noPresetsMessage": {}, + "noLogsMessage": "Não existem registos de alarmes", + "@noLogsMessage": {}, + "cancelSkipAlarmButton": "Cancelar ignorar", + "@cancelSkipAlarmButton": {}, + "dateFilterGroup": "Data", + "@dateFilterGroup": {}, + "scheduleDateFilterGroup": "Data de agendamento", + "@scheduleDateFilterGroup": {}, + "inactiveFilter": "Inativo", + "@inactiveFilter": {}, + "runningTimerFilter": "Em execução", + "@runningTimerFilter": {}, + "pausedTimerFilter": "Em pausa", + "@pausedTimerFilter": {}, + "stoppedTimerFilter": "Parado", + "@stoppedTimerFilter": {}, + "sortGroup": "Organizar", + "@sortGroup": {}, + "nameAsc": "Nome (A-Z)", + "@nameAsc": {}, + "nameDesc": "Nome (Z-A)", + "@nameDesc": {}, + "materialBrightnessLight": "Claro", + "@materialBrightnessLight": {}, + "accentColorSetting": "Cor de destaque", + "@accentColorSetting": {}, + "audioChannelAlarm": "Alarme", + "@audioChannelAlarm": {}, + "audioChannelNotification": "Notificação", + "@audioChannelNotification": {}, + "audioChannelRingtone": "Toque", + "@audioChannelRingtone": {}, + "audioChannelMedia": "Multimédia", + "@audioChannelMedia": {}, + "dismissAlarmButton": "Descartar", + "@dismissAlarmButton": {}, + "createdDateFilterGroup": "Data de criação", + "@createdDateFilterGroup": {}, + "stateFilterGroup": "Estado", + "@stateFilterGroup": {}, + "activeFilter": "Ativo", + "@activeFilter": {}, + "defaultLabel": "Padrão", + "@defaultLabel": {}, + "durationAsc": "Mais curta", + "@durationAsc": {}, + "durationDesc": "Mais longa", + "@durationDesc": {}, + "logTypeFilterGroup": "Tipo", + "@logTypeFilterGroup": {}, + "accentLabel": "Destaque", + "@accentLabel": {}, + "errorLabel": "Erro", + "@errorLabel": {}, + "materialBrightnessSystem": "Sistema", + "@materialBrightnessSystem": {}, + "materialBrightnessDark": "Escuro", + "@materialBrightnessDark": {}, + "alarmWeekdaysSetting": "Dias da semana", + "@alarmWeekdaysSetting": {}, + "alarmIntervalWeekly": "Semanalmente", + "@alarmIntervalWeekly": {}, + "alarmDatesSetting": "Datas", + "@alarmDatesSetting": {}, + "alarmRangeSetting": "Intervalo de data", + "@alarmRangeSetting": {}, + "alarmIntervalSetting": "Intervalo", + "@alarmIntervalSetting": {}, + "alarmIntervalDaily": "Diariamente", + "@alarmIntervalDaily": {}, + "cannotDisableAlarmWhileSnoozedSnackbar": "Não pode desativar o alarme se estiver em snooze", + "@cannotDisableAlarmWhileSnoozedSnackbar": {}, + "filterActions": "Ações de filtros", + "@filterActions": {}, + "clearFiltersAction": "Limpar todos", + "@clearFiltersAction": {}, + "deleteAllFilteredAction": "Eliminar alarmes filtrados", + "@deleteAllFilteredAction": {}, + "alarmDescriptionWeekly": "A cada {days}", + "@alarmDescriptionWeekly": {}, + "defaultSettingGroup": "Definições padrão", + "@defaultSettingGroup": {}, + "alarmsDefaultSettingGroupDescription": "Definir valores padrão para novos alarmes", + "@alarmsDefaultSettingGroupDescription": {}, + "timerDefaultSettingGroupDescription": "Definir valores padrão para novos temporizadores", + "@timerDefaultSettingGroupDescription": {}, + "filtersSettingGroup": "Filtros", + "@filtersSettingGroup": {}, + "showFiltersSetting": "Mostrar filtros", + "@showFiltersSetting": {}, + "showSortSetting": "Mostrar ordenados", + "@showSortSetting": {}, + "notificationsSettingGroup": "Notificações", + "@notificationsSettingGroup": {}, + "cancelSkipAllFilteredAlarmsAction": "Cancelar Ignorar alarmes filtrados", + "@cancelSkipAllFilteredAlarmsAction": {}, + "enableAllFilteredAlarmsAction": "Ativar alarmes filtrados", + "@enableAllFilteredAlarmsAction": {}, + "disableAllFilteredAlarmsAction": "Desativar alarmes filtrados", + "@disableAllFilteredAlarmsAction": {}, + "skipAllFilteredAlarmsAction": "Ignorar alarmes filtrados", + "@skipAllFilteredAlarmsAction": {} +} diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb new file mode 100644 index 00000000..80d9128b --- /dev/null +++ b/lib/l10n/app_ru.arb @@ -0,0 +1,168 @@ +{ + "clockTitle": "Часы", + "@clockTitle": { + "description": "Title of the clock screen" + }, + "alarmTitle": "Будильник", + "@alarmTitle": { + "description": "Title of the alarm screen" + }, + "timerTitle": "Таймер", + "@timerTitle": { + "description": "Title of the timer screen" + }, + "stopwatchTitle": "Секундомер", + "@stopwatchTitle": { + "description": "Title of the stopwatch screen" + }, + "generalSettingGroup": "Основные настройки", + "@generalSettingGroup": {}, + "appearanceSettingGroup": "Внешний вид", + "@appearanceSettingGroup": {}, + "accessibilitySettingGroup": "Специальные возможности", + "@accessibilitySettingGroup": {}, + "developerOptionsSettingGroup": "Для разработчиков", + "@developerOptionsSettingGroup": {}, + "restoreSettingGroup": "Восстановить настройки по умолчанию", + "@restoreSettingGroup": {}, + "displaySettingGroup": "Экран", + "@displaySettingGroup": {}, + "colorsSettingGroup": "Цвета", + "@colorsSettingGroup": {}, + "useMaterialYouColorSetting": "Использовать Material You дизайн", + "@useMaterialYouColorSetting": {}, + "overrideAccentSetting": "Изменить цвет акцента", + "@overrideAccentSetting": {}, + "materialBrightnessSetting": "Тёмная тема", + "@materialBrightnessSetting": {}, + "styleThemeSetting": "Тема", + "@styleThemeSetting": {}, + "useMaterialStyleSetting": "Использовать Material дизайн", + "@useMaterialStyleSetting": {}, + "colorSchemeSetting": "Цветовая схема", + "@colorSchemeSetting": {}, + "darkColorSchemeSetting": "Тёмная тема", + "@darkColorSchemeSetting": {}, + "clockSettingGroup": "Часы", + "@clockSettingGroup": {}, + "timerSettingGroup": "Таймер", + "@timerSettingGroup": {}, + "stopwatchSettingGroup": "Секундомер", + "@stopwatchSettingGroup": {}, + "generalSettingGroupDescription": "Изменить основные настройки приложения, такие как формат часов", + "@generalSettingGroupDescription": {}, + "appearanceSettingGroupDescription": "Изменить тему, цвета и внешний вид", + "@appearanceSettingGroupDescription": {}, + "cancelButton": "Отмена", + "@cancelButton": {}, + "customizeButton": "Настроить", + "@customizeButton": {}, + "saveButton": "Сохранить", + "@saveButton": {}, + "vibrationSetting": "Вибрация", + "@vibrationSetting": {}, + "backupSettingGroup": "Настройки", + "@backupSettingGroup": {}, + "systemDarkModeSetting": "Тёмная тема системы", + "@systemDarkModeSetting": {}, + "system": "Система", + "@system": {}, + "languageSetting": "Язык", + "@languageSetting": {}, + "dateFormatSetting": "Формат даты", + "@dateFormatSetting": {}, + "timeFormatSetting": "Формат времени", + "@timeFormatSetting": {}, + "timeFormat12": "12 часов", + "@timeFormat12": {}, + "timeFormat24": "24 часа", + "@timeFormat24": {}, + "timeFormatDevice": "Настройки устройства", + "@timeFormatDevice": {}, + "showSecondsSetting": "Показать секунды", + "@showSecondsSetting": {}, + "swipeActionCardActionDescription": "Смахните карточку влево или вправо, чтобы выполнить действие", + "@swipeActionCardActionDescription": {}, + "batteryOptimizationSetting": "Отключить оптимизацию батареи", + "@batteryOptimizationSetting": {}, + "batteryOptimizationSettingDescription": "Отключить оптимизацию батареи для этого приложения, чтобы избежать откладывания будильника", + "@batteryOptimizationSettingDescription": {}, + "allowNotificationSetting": "Разрешить уведомления", + "@allowNotificationSetting": {}, + "autoStartSetting": "Автозапуск", + "@autoStartSetting": {}, + "animationSettingGroup": "Анимации", + "@animationSettingGroup": {}, + "animationSpeedSetting": "Скорость анимации", + "@animationSpeedSetting": {}, + "extraAnimationSetting": "Дополнительные анимации", + "@extraAnimationSetting": {}, + "nameField": "Имя", + "@nameField": {}, + "colorSetting": "Цвет", + "@colorSetting": {}, + "swipeActionSetting": "Смахивание", + "@swipeActionSetting": {}, + "swipActionCardAction": "Действия карточки", + "@swipActionCardAction": {}, + "swipActionSwitchTabs": "Сменить вкладу", + "@swipActionSwitchTabs": {}, + "melodiesSetting": "Мелодии", + "@melodiesSetting": {}, + "tagsSetting": "Ярлыки", + "@tagsSetting": {}, + "colorSchemeBackgroundSettingGroup": "Фон", + "@colorSchemeBackgroundSettingGroup": {}, + "colorSchemeAccentSettingGroup": "Акцент", + "@colorSchemeAccentSettingGroup": {}, + "colorSchemeCardSettingGroup": "Карточка", + "@colorSchemeCardSettingGroup": {}, + "colorSchemeOutlineSettingGroup": "Граница", + "@colorSchemeOutlineSettingGroup": {}, + "colorSchemeShadowSettingGroup": "Тень", + "@colorSchemeShadowSettingGroup": {}, + "colorSchemeUseAccentAsOutlineSetting": "Использовать акцент для границ", + "@colorSchemeUseAccentAsOutlineSetting": {}, + "colorSchemeUseAccentAsShadowSetting": "Использовать акцент для теней", + "@colorSchemeUseAccentAsShadowSetting": {}, + "styleThemeShadowSettingGroup": "Тень", + "@styleThemeShadowSettingGroup": {}, + "styleThemeShapeSettingGroup": "Форма", + "@styleThemeShapeSettingGroup": {}, + "styleThemeRadiusSetting": "Скругление углов", + "@styleThemeRadiusSetting": {}, + "styleThemeBlurSetting": "Размытие", + "@styleThemeBlurSetting": {}, + "styleThemeOutlineSettingGroup": "Граница", + "@styleThemeOutlineSettingGroup": {}, + "styleThemeOutlineWidthSetting": "Ширина", + "@styleThemeOutlineWidthSetting": {}, + "resetButton": "Сбросить", + "@resetButton": {}, + "cardLabel": "Карточка", + "@cardLabel": {}, + "accentLabel": "Акцент", + "@accentLabel": {}, + "errorLabel": "Ошибка", + "@errorLabel": {}, + "materialBrightnessSystem": "Система", + "@materialBrightnessSystem": {}, + "materialBrightnessLight": "Светлая", + "@materialBrightnessLight": {}, + "materialBrightnessDark": "Тёмная", + "@materialBrightnessDark": {}, + "accentColorSetting": "Цвет акцента", + "@accentColorSetting": {}, + "textColorSetting": "Текст", + "@textColorSetting": {}, + "colorSchemeErrorSettingGroup": "Ошибка", + "@colorSchemeErrorSettingGroup": {}, + "styleThemeOpacitySetting": "Прозрачность", + "@styleThemeOpacitySetting": {}, + "colorSchemeNamePlaceholder": "Цветовая схема", + "@colorSchemeNamePlaceholder": {}, + "vendorSetting": "Настройки производителя", + "@vendorSetting": {}, + "timePickerSetting": "Выбор времени", + "@timePickerSetting": {} +} diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb new file mode 100644 index 00000000..f6fe9b38 --- /dev/null +++ b/lib/l10n/app_tr.arb @@ -0,0 +1,228 @@ +{ + "clockTitle": "Saat", + "@clockTitle": { + "description": "Title of the clock screen" + }, + "alarmTitle": "Alarm", + "@alarmTitle": { + "description": "Title of the alarm screen" + }, + "timerTitle": "Zamanlayıcı", + "@timerTitle": { + "description": "Title of the timer screen" + }, + "stopwatchTitle": "Kronometre", + "@stopwatchTitle": { + "description": "Title of the stopwatch screen" + }, + "generalSettingGroup": "Genel", + "@generalSettingGroup": {}, + "appearanceSettingGroup": "Görünüm", + "@appearanceSettingGroup": {}, + "backupSettingGroup": "Yedekleme", + "@backupSettingGroup": {}, + "aboutSettingGroup": "Hakkında", + "@aboutSettingGroup": {}, + "restoreSettingGroup": "Varsayılan değerlere geri yükle", + "@restoreSettingGroup": {}, + "displaySettingGroup": "Görünüm", + "@displaySettingGroup": {}, + "reliabilitySettingGroup": "Güvenlik", + "@reliabilitySettingGroup": {}, + "colorsSettingGroup": "Renkler", + "@colorsSettingGroup": {}, + "styleSettingGroup": "Tarz", + "@styleSettingGroup": {}, + "useMaterialYouColorSetting": "Material You kullan", + "@useMaterialYouColorSetting": {}, + "materialBrightnessSetting": "Görünüm", + "@materialBrightnessSetting": {}, + "overrideAccentSetting": "Vurgu rengini geçersiz kıl", + "@overrideAccentSetting": {}, + "developerOptionsSettingGroup": "Geliştirici seçenekleri", + "@developerOptionsSettingGroup": {}, + "useMaterialStyleSetting": "Material tarzını kullan", + "@useMaterialStyleSetting": {}, + "styleThemeSetting": "Tarz teması", + "@styleThemeSetting": {}, + "systemDarkModeSetting": "Sistem karanlık biçemi", + "@systemDarkModeSetting": {}, + "colorSchemeSetting": "Renk uyumu", + "@colorSchemeSetting": {}, + "darkColorSchemeSetting": "Koyu renk tarzı", + "@darkColorSchemeSetting": {}, + "clockSettingGroup": "Saat", + "@clockSettingGroup": {}, + "timerSettingGroup": "Zamanlayıcı", + "@timerSettingGroup": {}, + "stopwatchSettingGroup": "Kronometre", + "@stopwatchSettingGroup": {}, + "generalSettingGroupDescription": "Saat biçimi gibi uygulama genelindeki ayarları belirle", + "@generalSettingGroupDescription": {}, + "selectTime": "Zaman seç", + "@selectTime": {}, + "alarmScheduleSettingGroup": "Zamanlama", + "@alarmScheduleSettingGroup": {}, + "scheduleTypeField": "Tip", + "@scheduleTypeField": {}, + "scheduleTypeOnce": "Bir kere", + "@scheduleTypeOnce": {}, + "scheduleTypeDaily": "Günlük", + "@scheduleTypeDaily": {}, + "scheduleTypeOnceDescription": "Bir sonraki seferde çalacak", + "@scheduleTypeOnceDescription": {}, + "scheduleTypeDailyDescription": "Her gün çalacak", + "@scheduleTypeDailyDescription": {}, + "scheduleTypeWeek": "Haftanın belirlenen günlerinde", + "@scheduleTypeWeek": {}, + "scheduleTypeWeekDescription": "Hafta içi belirlenen günlerde tekrarlanacak", + "@scheduleTypeWeekDescription": {}, + "scheduleTypeRange": "Tarih aralığı", + "@scheduleTypeRange": {}, + "scheduleTypeDateDescription": "Belirlenen tarihlerde tekrarlanacak", + "@scheduleTypeDateDescription": {}, + "scheduleTypeRangeDescription": "Belirlenen tarih aralığında tekrarlanacak", + "@scheduleTypeRangeDescription": {}, + "settingGroupMore": "Daha fazla", + "@settingGroupMore": {}, + "melodySetting": "Melodi", + "@melodySetting": {}, + "vibrationSetting": "Titreşim", + "@vibrationSetting": {}, + "audioChannelSetting": "Ses kanalı", + "@audioChannelSetting": {}, + "volumeSetting": "Ses", + "@volumeSetting": {}, + "risingVolumeSetting": "Yükselen ses", + "@risingVolumeSetting": {}, + "snoozeSettingGroup": "Ertele", + "@snoozeSettingGroup": {}, + "snoozeEnableSetting": "Aktif", + "@snoozeEnableSetting": {}, + "snoozeLengthSetting": "Süre", + "@snoozeLengthSetting": {}, + "whileSnoozedSettingGroup": "Ertelenmişken", + "@whileSnoozedSettingGroup": {}, + "snoozePreventDisablingSetting": "Devre dışı bırakmayı önle", + "@snoozePreventDisablingSetting": {}, + "settings": "Ayarlar", + "@settings": {}, + "tasksSetting": "Görevler", + "@tasksSetting": {}, + "noItemMessage": "Henüz {items} eklenmedi", + "@noItemMessage": {}, + "chooseTaskTitle": "Eklenecek görevi seç", + "@chooseTaskTitle": {}, + "mathTask": "Matematik problemleri", + "@mathTask": {}, + "sequenceTask": "Sekans", + "@sequenceTask": {}, + "mathTaskDifficultySetting": "Zorluk", + "@mathTaskDifficultySetting": {}, + "retypeNumberChars": "Karakter sayısı", + "@retypeNumberChars": {}, + "retypeIncludeNumSetting": "Sayıları dahil et", + "@retypeIncludeNumSetting": {}, + "retypeLowercaseSetting": "Küçük harfleri dahil et", + "@retypeLowercaseSetting": {}, + "sequenceLengthSetting": "Sekans uzunluğu", + "@sequenceLengthSetting": {}, + "sequenceGridSizeSetting": "Izgara boyutu", + "@sequenceGridSizeSetting": {}, + "saveReminderAlert": "Kaydetmeden ayrılmak istiyor musun?", + "@saveReminderAlert": {}, + "yesButton": "Evet", + "@yesButton": {}, + "deleteButton": "Sil", + "@deleteButton": {}, + "alarmDescriptionNotScheduled": "Planlanmadı", + "@alarmDescriptionNotScheduled": {}, + "alarmDescriptionToday": "Sadece bugün", + "@alarmDescriptionToday": {}, + "alarmDescriptionTomorrow": "Sadece yarın", + "@alarmDescriptionTomorrow": {}, + "alarmDescriptionEveryDay": "Her gün", + "@alarmDescriptionEveryDay": {}, + "alarmDescriptionDays": "{days} tarihinde", + "@alarmDescriptionDays": {}, + "alarmDescriptionDates": "{date}{count, plural, =0{} =1{ ve 1 başka tarih} other{ ve {count} diğer tarih}}", + "@alarmDescriptionDates": {}, + "stopwatchAverage": "Ortalama", + "@stopwatchAverage": {}, + "accessibilitySettingGroup": "Erişilebilirlik", + "@accessibilitySettingGroup": {}, + "saveButton": "Kaydet düğmesi", + "@saveButton": {}, + "labelField": "Etiket", + "@labelField": {}, + "appearanceSettingGroupDescription": "Temaları, renkleri ayarla ve düzeni değiştir", + "@appearanceSettingGroupDescription": {}, + "labelFieldPlaceholder": "Bir etiket ekle", + "@labelFieldPlaceholder": {}, + "backupSettingGroupDescription": "Ayarları yerel olarak dışa veya içe aktar", + "@backupSettingGroupDescription": {}, + "cancelButton": "İptal", + "@cancelButton": {}, + "customizeButton": "Özelleştir", + "@customizeButton": {}, + "soundSettingGroup": "Ses ve Titreşim", + "@soundSettingGroup": {}, + "retypeTask": "Metni yeniden yaz", + "@retypeTask": {}, + "noButton": "Hayır", + "@noButton": {}, + "todayFilter": "Bugün", + "@todayFilter": {}, + "duplicateButton": "Çoğalt", + "@duplicateButton": {}, + "skipAlarmButton": "Sonraki alarmı atla", + "@skipAlarmButton": {}, + "allFilter": "Tümü", + "@allFilter": {}, + "tomorrowFilter": "Yarın", + "@tomorrowFilter": {}, + "snoozedFilter": "Ertelendi", + "@snoozedFilter": {}, + "disabledFilter": "Engellendi", + "@disabledFilter": {}, + "completedFilter": "Tamamlandı", + "@completedFilter": {}, + "alarmDescriptionSnooze": "{date} tarihine kadar ertelendi", + "@alarmDescriptionSnooze": {}, + "alarmDescriptionFinished": "Sonraki tarih yok", + "@alarmDescriptionFinished": {}, + "alarmDescriptionRange": "{interval, select, daily{Günlük} weekly{Haftalık} other{Other}} - {startDate} - {endDate} arası", + "@alarmDescriptionRange": {}, + "alarmDescriptionWeekend": "Her hafta sonu", + "@alarmDescriptionWeekend": {}, + "stopwatchPrevious": "Önceki", + "@stopwatchPrevious": {}, + "stopwatchSlowest": "En yavaş", + "@stopwatchSlowest": {}, + "alarmDescriptionWeekday": "Hafta içi her gün", + "@alarmDescriptionWeekday": {}, + "stopwatchFastest": "En hızlı", + "@stopwatchFastest": {}, + "taskTryButton": "Dene", + "@taskTryButton": {}, + "skippingDescriptionSuffix": "(sonraki atlanacak)", + "@skippingDescriptionSuffix": {}, + "system": "Dizge", + "@system": {}, + "languageSetting": "Dil", + "@languageSetting": {}, + "dateFormatSetting": "Tarih Biçimi", + "@dateFormatSetting": {}, + "timeFormatSetting": "Saat Biçimi", + "@timeFormatSetting": {}, + "timeFormat12": "12 saat", + "@timeFormat12": {}, + "timeFormat24": "24 saat", + "@timeFormat24": {}, + "timeFormatDevice": "Cihaz Ayarları", + "@timeFormatDevice": {}, + "showSecondsSetting": "Saniye Göster", + "@showSecondsSetting": {}, + "pickerInput": "Girdi", + "@pickerInput": {} +} diff --git a/lib/l10n/app_vi.arb b/lib/l10n/app_vi.arb new file mode 100644 index 00000000..d4f09934 --- /dev/null +++ b/lib/l10n/app_vi.arb @@ -0,0 +1,252 @@ +{ + "sequenceGridSizeSetting": "Kích thước lưới", + "@sequenceGridSizeSetting": {}, + "scheduleTypeWeekDescription": "Sẽ lặp lại vào các ngày trong tuần được chỉ định", + "@scheduleTypeWeekDescription": {}, + "soundSettingGroup": "Âm thanh và Rung", + "@soundSettingGroup": {}, + "saveReminderAlert": "Bạn có muốn rời đi mà không lưu?", + "@saveReminderAlert": {}, + "scheduleTypeDaily": "Hằng ngày", + "@scheduleTypeDaily": {}, + "yesButton": "Có", + "@yesButton": {}, + "scheduleTypeDateDescription": "Sẽ lặp lại vào những ngày được chỉ định", + "@scheduleTypeDateDescription": {}, + "scheduleTypeRangeDescription": "Sẽ lặp lại trong phạm vi ngày được chỉ định", + "@scheduleTypeRangeDescription": {}, + "settingGroupMore": "Nhiều hơn", + "@settingGroupMore": {}, + "scheduleTypeRange": "Phạm vi ngày", + "@scheduleTypeRange": {}, + "selectTime": "Chọn thời gian", + "@selectTime": {}, + "cancelButton": "Hủy", + "@cancelButton": {}, + "customizeButton": "Tùy chỉnh", + "@customizeButton": {}, + "alarmDescriptionToday": "Chỉ hôm nay", + "@alarmDescriptionToday": {}, + "snoozedFilter": "Đã hoãn", + "@snoozedFilter": {}, + "stopwatchSettingGroup": "Bấm giờ", + "@stopwatchSettingGroup": {}, + "scheduleTypeOnceDescription": "Sẽ đổ chuông vào lần xuất hiện tiếp theo của thời điểm", + "@scheduleTypeOnceDescription": {}, + "scheduleTypeWeek": "Vào Ngày trong tuần được chỉ định", + "@scheduleTypeWeek": {}, + "melodySetting": "Giai điệu", + "@melodySetting": {}, + "scheduleTypeField": "Loại", + "@scheduleTypeField": {}, + "scheduleTypeOnce": "Một lần", + "@scheduleTypeOnce": {}, + "vibrationSetting": "Rung", + "@vibrationSetting": {}, + "alarmTitle": "Báo thức", + "@alarmTitle": { + "description": "Title of the alarm screen" + }, + "timerTitle": "Hẹn giờ", + "@timerTitle": { + "description": "Title of the timer screen" + }, + "stopwatchTitle": "Bấm giờ", + "@stopwatchTitle": { + "description": "Title of the stopwatch screen" + }, + "generalSettingGroup": "Tổng quan", + "@generalSettingGroup": {}, + "appearanceSettingGroup": "Diện mạo", + "@appearanceSettingGroup": {}, + "aboutSettingGroup": "Giới thiệu", + "@aboutSettingGroup": {}, + "restoreSettingGroup": "Khôi phục giá trị mặc định", + "@restoreSettingGroup": {}, + "displaySettingGroup": "Hiển thị", + "@displaySettingGroup": {}, + "reliabilitySettingGroup": "Độ tin cậy", + "@reliabilitySettingGroup": {}, + "colorsSettingGroup": "Màu sắc", + "@colorsSettingGroup": {}, + "styleSettingGroup": "Phong cách", + "@styleSettingGroup": {}, + "useMaterialYouColorSetting": "Sử dụng Material You", + "@useMaterialYouColorSetting": {}, + "materialBrightnessSetting": "Độ sáng", + "@materialBrightnessSetting": {}, + "overrideAccentSetting": "Ghi đè màu nhấn", + "@overrideAccentSetting": {}, + "useMaterialStyleSetting": "Sử dụng phong cách Material", + "@useMaterialStyleSetting": {}, + "styleThemeSetting": "Chủ đề phong cách", + "@styleThemeSetting": {}, + "systemDarkModeSetting": "Chế độ tối của hệ thống", + "@systemDarkModeSetting": {}, + "darkColorSchemeSetting": "Phối màu tối", + "@darkColorSchemeSetting": {}, + "clockSettingGroup": "Đồng hồ", + "@clockSettingGroup": {}, + "timerSettingGroup": "Hẹn giờ", + "@timerSettingGroup": {}, + "generalSettingGroupDescription": "Đặt cài đặt trên toàn ứng dụng như định dạng thời gian", + "@generalSettingGroupDescription": {}, + "appearanceSettingGroupDescription": "Đặt chủ đề, màu sắc và thay đổi bố cục", + "@appearanceSettingGroupDescription": {}, + "backupSettingGroupDescription": "Xuất hoặc nhập thiết đặt của bạn cục bộ", + "@backupSettingGroupDescription": {}, + "saveButton": "Nút lưu", + "@saveButton": {}, + "labelField": "Nhãn", + "@labelField": {}, + "labelFieldPlaceholder": "Thêm nhãn", + "@labelFieldPlaceholder": {}, + "alarmScheduleSettingGroup": "Lịch trình", + "@alarmScheduleSettingGroup": {}, + "audioChannelSetting": "Kênh âm thanh", + "@audioChannelSetting": {}, + "volumeSetting": "Âm lượng", + "@volumeSetting": {}, + "risingVolumeSetting": "Tăng âm lượng", + "@risingVolumeSetting": {}, + "snoozeSettingGroup": "Hoãn", + "@snoozeSettingGroup": {}, + "snoozeEnableSetting": "Đã bật", + "@snoozeEnableSetting": {}, + "snoozeLengthSetting": "Thời lượng", + "@snoozeLengthSetting": {}, + "whileSnoozedSettingGroup": "Trong khi hoãn", + "@whileSnoozedSettingGroup": {}, + "snoozePreventDisablingSetting": "Ngăn chặn việc vô hiệu hóa", + "@snoozePreventDisablingSetting": {}, + "settings": "Thiết đặt", + "@settings": {}, + "noItemMessage": "Chưa có {items} nào được thêm vào", + "@noItemMessage": {}, + "chooseTaskTitle": "Chọn nhiệm vụ để thêm", + "@chooseTaskTitle": {}, + "mathTask": "Bài toán", + "@mathTask": {}, + "retypeTask": "Nhập lại văn bản", + "@retypeTask": {}, + "mathTaskDifficultySetting": "Độ khó", + "@mathTaskDifficultySetting": {}, + "retypeNumberChars": "Số ký tự", + "@retypeNumberChars": {}, + "retypeIncludeNumSetting": "Bao gồm số", + "@retypeIncludeNumSetting": {}, + "retypeLowercaseSetting": "Bao gồm chữ thường", + "@retypeLowercaseSetting": {}, + "noButton": "Không", + "@noButton": {}, + "deleteButton": "Xóa", + "@deleteButton": {}, + "duplicateButton": "Nhân đôi", + "@duplicateButton": {}, + "skipAlarmButton": "Bỏ qua báo thức tiếp theo", + "@skipAlarmButton": {}, + "allFilter": "Tất cả", + "@allFilter": {}, + "todayFilter": "Hôm nay", + "@todayFilter": {}, + "tomorrowFilter": "Ngày mai", + "@tomorrowFilter": {}, + "disabledFilter": "Đã tắt", + "@disabledFilter": {}, + "completedFilter": "Hoàn thành", + "@completedFilter": {}, + "skippingDescriptionSuffix": "(bỏ qua lần xuất hiện tiếp theo)", + "@skippingDescriptionSuffix": {}, + "alarmDescriptionSnooze": "Đã hoãn cho đến {date}", + "@alarmDescriptionSnooze": {}, + "alarmDescriptionFinished": "Không có ngày trong tương lai", + "@alarmDescriptionFinished": {}, + "alarmDescriptionNotScheduled": "Chưa lên lịch", + "@alarmDescriptionNotScheduled": {}, + "sequenceTask": "Dãy", + "@sequenceTask": {}, + "taskTryButton": "Dùng thử", + "@taskTryButton": {}, + "sequenceLengthSetting": "Chiều dài dãy", + "@sequenceLengthSetting": {}, + "stopwatchPrevious": "Trước đó", + "@stopwatchPrevious": {}, + "stopwatchFastest": "Nhanh nhất", + "@stopwatchFastest": {}, + "stopwatchSlowest": "Chậm nhất", + "@stopwatchSlowest": {}, + "stopwatchAverage": "Trung bình", + "@stopwatchAverage": {}, + "alarmDescriptionTomorrow": "Chỉ ngày mai", + "@alarmDescriptionTomorrow": {}, + "alarmDescriptionEveryDay": "Hằng ngày", + "@alarmDescriptionEveryDay": {}, + "alarmDescriptionWeekend": "Mỗi cuối tuần", + "@alarmDescriptionWeekend": {}, + "alarmDescriptionWeekday": "Mỗi ngày trong tuần", + "@alarmDescriptionWeekday": {}, + "alarmDescriptionDays": "Vào {days}", + "@alarmDescriptionDays": {}, + "alarmDescriptionRange": "{interval, select, daily{Daily} weekly{Weekly} other{Other}} từ {startDate} tới {endDate}", + "@alarmDescriptionRange": {}, + "alarmDescriptionDates": "Vào {date}{count, plural, =0{} =1{ and 1 other date} other{ and {count} other dates}}", + "@alarmDescriptionDates": {}, + "clockTitle": "Đồng hồ", + "@clockTitle": { + "description": "Title of the clock screen" + }, + "accessibilitySettingGroup": "Khả năng tiếp cận", + "@accessibilitySettingGroup": {}, + "backupSettingGroup": "Sao lưu", + "@backupSettingGroup": {}, + "developerOptionsSettingGroup": "Tùy chọn nhà phát triển", + "@developerOptionsSettingGroup": {}, + "tasksSetting": "Nhiệm vụ", + "@tasksSetting": {}, + "colorSchemeSetting": "Phối màu", + "@colorSchemeSetting": {}, + "scheduleTypeDailyDescription": "Sẽ đổ chuông mỗi ngày", + "@scheduleTypeDailyDescription": {}, + "swipeActionCardActionDescription": "Vuốt sang trái hoặc phải trên thẻ để thực hiện hành động", + "@swipeActionCardActionDescription": {}, + "batteryOptimizationSetting": "Tắt tối ưu hóa pin", + "@batteryOptimizationSetting": {}, + "system": "Hệ thống", + "@system": {}, + "languageSetting": "Ngôn ngữ", + "@languageSetting": {}, + "dateFormatSetting": "Định dạng ngày tháng", + "@dateFormatSetting": {}, + "timeFormatSetting": "Định dạng thời gian", + "@timeFormatSetting": {}, + "timeFormat12": "12 giờ", + "@timeFormat12": {}, + "timeFormat24": "24 giờ", + "@timeFormat24": {}, + "timeFormatDevice": "Thiết đặt thiết bị", + "@timeFormatDevice": {}, + "showSecondsSetting": "Hiển thị giây", + "@showSecondsSetting": {}, + "timePickerSetting": "Bộ chọn thời gian", + "@timePickerSetting": {}, + "pickerDial": "Quay số", + "@pickerDial": {}, + "durationPickerSetting": "Bộ chọn thời lượng", + "@durationPickerSetting": {}, + "pickerRings": "Chuông", + "@pickerRings": {}, + "swipeActionSetting": "Hành động vuốt", + "@swipeActionSetting": {}, + "swipActionCardAction": "Hành động thẻ", + "@swipActionCardAction": {}, + "swipActionSwitchTabs": "Chuyển tab", + "@swipActionSwitchTabs": {}, + "swipeActionSwitchTabsDescription": "Vuốt giữa các tab", + "@swipeActionSwitchTabsDescription": {}, + "melodiesSetting": "Giai điệu", + "@melodiesSetting": {}, + "vendorSetting": "Thiết đặt nhà cung cấp", + "@vendorSetting": {}, + "vendorSettingDescription": "Tắt thủ công các tối ưu hóa dành riêng cho nhà cung cấp", + "@vendorSettingDescription": {} +} diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb new file mode 100644 index 00000000..d066d428 --- /dev/null +++ b/lib/l10n/app_zh.arb @@ -0,0 +1,610 @@ +{ + "timerTitle": "计时器", + "@timerTitle": { + "description": "Title of the timer screen" + }, + "stopwatchTitle": "秒表", + "@stopwatchTitle": { + "description": "Title of the stopwatch screen" + }, + "system": "系统", + "@system": {}, + "generalSettingGroupDescription": "应用的全局设置,如时间格式", + "@generalSettingGroupDescription": {}, + "timeFormatSetting": "时间格式", + "@timeFormatSetting": {}, + "timeFormat12": "12小时制", + "@timeFormat12": {}, + "timeFormat24": "24小时制", + "@timeFormat24": {}, + "timeFormatDevice": "跟随系统设置", + "@timeFormatDevice": {}, + "timePickerSetting": "时间选择器样式", + "@timePickerSetting": {}, + "swipActionCardAction": "操作卡片", + "@swipActionCardAction": {}, + "pickerSpinner": "转盘", + "@pickerSpinner": {}, + "durationPickerSetting": "计时器时长选择器", + "@durationPickerSetting": {}, + "pickerRings": "环状", + "@pickerRings": {}, + "swipeActionSetting": "滑动操作", + "@swipeActionSetting": {}, + "melodiesSetting": "铃声", + "@melodiesSetting": {}, + "tagsSetting": "标签", + "@tagsSetting": {}, + "batteryOptimizationSettingDescription": "禁用制造商的电池优化,以防止闹钟延迟响铃", + "@batteryOptimizationSettingDescription": {}, + "allowNotificationSettingDescription": "打开闹钟和计时器的锁屏通知", + "@allowNotificationSettingDescription": {}, + "vendorSetting": "制造商设置", + "@vendorSetting": {}, + "allowNotificationSetting": "打开通知", + "@allowNotificationSetting": {}, + "autoStartSetting": "自启动", + "@autoStartSetting": {}, + "animationSettingGroup": "动画", + "@animationSettingGroup": {}, + "animationSpeedSetting": "动画速度", + "@animationSpeedSetting": {}, + "extraAnimationSetting": "启用更多动画", + "@extraAnimationSetting": {}, + "appearanceSettingGroup": "外观", + "@appearanceSettingGroup": {}, + "clockTitle": "时钟", + "@clockTitle": { + "description": "Title of the clock screen" + }, + "alarmTitle": "闹钟", + "@alarmTitle": { + "description": "Title of the alarm screen" + }, + "generalSettingGroup": "通用设置", + "@generalSettingGroup": {}, + "languageSetting": "语言", + "@languageSetting": {}, + "dateFormatSetting": "日期格式", + "@dateFormatSetting": {}, + "showSecondsSetting": "显示秒数", + "@showSecondsSetting": {}, + "pickerInput": "输入框", + "@pickerInput": {}, + "swipeActionCardActionDescription": "向左或向右滑动卡片以执行操作", + "@swipeActionCardActionDescription": {}, + "swipActionSwitchTabs": "切换选项卡", + "@swipActionSwitchTabs": {}, + "swipeActionSwitchTabsDescription": "在选项卡间切换", + "@swipeActionSwitchTabsDescription": {}, + "batteryOptimizationSetting": "禁用电池优化", + "@batteryOptimizationSetting": {}, + "vendorSettingDescription": "手动关闭特定制造商的优化设置", + "@vendorSettingDescription": {}, + "autoStartSettingDescription": "对于部分设备,应用需要“自启动”权限以在关闭时响铃", + "@autoStartSettingDescription": {}, + "pickerDial": "拨盘", + "@pickerDial": {}, + "appearanceSettingGroupDescription": "设置主题、颜色和布局", + "@appearanceSettingGroupDescription": {}, + "nameField": "名称", + "@nameField": {}, + "colorSetting": "颜色", + "@colorSetting": {}, + "textColorSetting": "文本", + "@textColorSetting": {}, + "colorSchemeBackgroundSettingGroup": "背景色", + "@colorSchemeBackgroundSettingGroup": {}, + "colorSchemeAccentSettingGroup": "强调色", + "@colorSchemeAccentSettingGroup": {}, + "colorSchemeCardSettingGroup": "卡片颜色", + "@colorSchemeCardSettingGroup": {}, + "colorSchemeOutlineSettingGroup": "轮廓色", + "@colorSchemeOutlineSettingGroup": {}, + "colorSchemeShadowSettingGroup": "阴影颜色", + "@colorSchemeShadowSettingGroup": {}, + "colorSchemeUseAccentAsOutlineSetting": "将强调色用于轮廓色", + "@colorSchemeUseAccentAsOutlineSetting": {}, + "colorSchemeUseAccentAsShadowSetting": "将强调色用于阴影", + "@colorSchemeUseAccentAsShadowSetting": {}, + "styleThemeNamePlaceholder": "样式主题", + "@styleThemeNamePlaceholder": {}, + "styleThemeShapeSettingGroup": "形状", + "@styleThemeShapeSettingGroup": {}, + "styleThemeRadiusSetting": "圆角半径", + "@styleThemeRadiusSetting": {}, + "styleThemeOutlineWidthSetting": "宽度", + "@styleThemeOutlineWidthSetting": {}, + "backupSettingGroup": "设置", + "@backupSettingGroup": {}, + "developerOptionsSettingGroup": "开发者设置", + "@developerOptionsSettingGroup": {}, + "styleThemeSpreadSetting": "散布", + "@styleThemeSpreadSetting": {}, + "accessibilitySettingGroup": "辅助功能", + "@accessibilitySettingGroup": {}, + "logsSettingGroup": "日志", + "@logsSettingGroup": {}, + "aboutSettingGroup": "关于", + "@aboutSettingGroup": {}, + "restoreSettingGroup": "恢复默认值", + "@restoreSettingGroup": {}, + "resetButton": "重置", + "@resetButton": {}, + "previewLabel": "预览", + "@previewLabel": {}, + "cardLabel": "卡片", + "@cardLabel": {}, + "accentLabel": "强调色", + "@accentLabel": {}, + "errorLabel": "错误", + "@errorLabel": {}, + "displaySettingGroup": "显示", + "@displaySettingGroup": {}, + "showIstantAlarmButtonSetting": "显示即时闹钟按钮", + "@showIstantAlarmButtonSetting": {}, + "showIstantTimerButtonSetting": "显示即时计时器按钮", + "@showIstantTimerButtonSetting": {}, + "useMaterialYouColorSetting": "使用 Material You 样式", + "@useMaterialYouColorSetting": {}, + "materialBrightnessSetting": "亮度", + "@materialBrightnessSetting": {}, + "materialBrightnessLight": "浅色", + "@materialBrightnessLight": {}, + "overrideAccentSetting": "覆盖强调色", + "@overrideAccentSetting": {}, + "accentColorSetting": "强调色", + "@accentColorSetting": {}, + "useMaterialStyleSetting": "使用 Material 风格", + "@useMaterialStyleSetting": {}, + "styleThemeSetting": "样式主题", + "@styleThemeSetting": {}, + "darkColorSchemeSetting": "深色主题", + "@darkColorSchemeSetting": {}, + "clockSettingGroup": "时钟", + "@clockSettingGroup": {}, + "stopwatchSettingGroup": "秒表", + "@stopwatchSettingGroup": {}, + "backupSettingGroupDescription": "在本地导出或导入设置", + "@backupSettingGroupDescription": {}, + "alarmWeekdaysSetting": "星期", + "@alarmWeekdaysSetting": {}, + "alarmDatesSetting": "日期", + "@alarmDatesSetting": {}, + "alarmRangeSetting": "日期范围", + "@alarmRangeSetting": {}, + "alarmIntervalSetting": "间隔", + "@alarmIntervalSetting": {}, + "alarmIntervalDaily": "每天", + "@alarmIntervalDaily": {}, + "alarmIntervalWeekly": "每周", + "@alarmIntervalWeekly": {}, + "alarmDeleteAfterRingingSetting": "关闭后删除", + "@alarmDeleteAfterRingingSetting": {}, + "alarmDeleteAfterFinishingSetting": "结束后删除", + "@alarmDeleteAfterFinishingSetting": {}, + "cannotDisableAlarmWhileSnoozedSnackbar": "无法禁用处于贪睡状态的闹钟", + "@cannotDisableAlarmWhileSnoozedSnackbar": {}, + "timePickerModeButton": "模式", + "@timePickerModeButton": {}, + "labelField": "标签", + "@labelField": {}, + "labelFieldPlaceholder": "添加标签", + "@labelFieldPlaceholder": {}, + "alarmScheduleSettingGroup": "时间计划", + "@alarmScheduleSettingGroup": {}, + "scheduleTypeDaily": "每天", + "@scheduleTypeDaily": {}, + "scheduleTypeOnceDescription": "将在下一次到达此时间时响铃", + "@scheduleTypeOnceDescription": {}, + "scheduleTypeDailyDescription": "将每天响铃", + "@scheduleTypeDailyDescription": {}, + "scheduleTypeWeek": "指定星期", + "@scheduleTypeWeek": {}, + "scheduleTypeWeekDescription": "将在指定星期重复响铃", + "@scheduleTypeWeekDescription": {}, + "scheduleTypeDate": "指定日期", + "@scheduleTypeDate": {}, + "scheduleTypeRange": "日期范围", + "@scheduleTypeRange": {}, + "settingGroupMore": "更多", + "@settingGroupMore": {}, + "scheduleTypeDateDescription": "将在指定日期重复响铃", + "@scheduleTypeDateDescription": {}, + "scheduleTypeRangeDescription": "将在指定日期范围内重复响铃", + "@scheduleTypeRangeDescription": {}, + "audioChannelSetting": "音频通道", + "@audioChannelSetting": {}, + "audioChannelAlarm": "闹钟", + "@audioChannelAlarm": {}, + "audioChannelMedia": "媒体", + "@audioChannelMedia": {}, + "volumeSetting": "音量", + "@volumeSetting": {}, + "snoozeSettingGroup": "贪睡", + "@snoozeSettingGroup": {}, + "snoozeEnableSetting": "启用", + "@snoozeEnableSetting": {}, + "risingVolumeSetting": "铃声渐响", + "@risingVolumeSetting": {}, + "timeToFullVolumeSetting": "至最大音量用时", + "@timeToFullVolumeSetting": {}, + "whileSnoozedSettingGroup": "处于贪睡状态时", + "@whileSnoozedSettingGroup": {}, + "settings": "设置", + "@settings": {}, + "tasksSetting": "任务", + "@tasksSetting": {}, + "noItemMessage": "还没有添加{items}", + "@noItemMessage": {}, + "chooseTaskTitle": "选择待添加任务", + "@chooseTaskTitle": {}, + "mathTask": "数学题", + "@mathTask": {}, + "mathEasyDifficulty": "简单 (X + Y)", + "@mathEasyDifficulty": {}, + "mathMediumDifficulty": "中等 (X × Y)", + "@mathMediumDifficulty": {}, + "retypeTask": "重输文本", + "@retypeTask": {}, + "sequenceTask": "数列", + "@sequenceTask": {}, + "taskTryButton": "试一试", + "@taskTryButton": {}, + "mathTaskDifficultySetting": "难度", + "@mathTaskDifficultySetting": {}, + "retypeLowercaseSetting": "包括小写字母", + "@retypeLowercaseSetting": {}, + "sequenceLengthSetting": "数列长度", + "@sequenceLengthSetting": {}, + "sequenceGridSizeSetting": "网格大小", + "@sequenceGridSizeSetting": {}, + "numberOfProblemsSetting": "问题数", + "@numberOfProblemsSetting": {}, + "saveReminderAlert": "你想要不保存退出吗?", + "@saveReminderAlert": {}, + "yesButton": "是", + "@yesButton": {}, + "noAlarmMessage": "未创建闹钟", + "@noAlarmMessage": {}, + "noTimerMessage": "未创建计时器", + "@noTimerMessage": {}, + "noStopwatchMessage": "未创建秒表", + "@noStopwatchMessage": {}, + "noTaskMessage": "未创建任务", + "@noTaskMessage": {}, + "noPresetsMessage": "未创建预设", + "@noPresetsMessage": {}, + "noLogsMessage": "无闹钟日志", + "@noLogsMessage": {}, + "deleteButton": "删除", + "@deleteButton": {}, + "skipAlarmButton": "跳过下次闹钟", + "@skipAlarmButton": {}, + "cancelSkipAlarmButton": "取消跳过", + "@cancelSkipAlarmButton": {}, + "scheduleDateFilterGroup": "计划日期", + "@scheduleDateFilterGroup": {}, + "todayFilter": "今天", + "@todayFilter": {}, + "completedFilter": "已完成", + "@completedFilter": {}, + "runningTimerFilter": "进行中", + "@runningTimerFilter": {}, + "pausedTimerFilter": "已暂停", + "@pausedTimerFilter": {}, + "stoppedTimerFilter": "已停止", + "@stoppedTimerFilter": {}, + "sortGroup": "排序", + "@sortGroup": {}, + "defaultLabel": "默认", + "@defaultLabel": {}, + "remainingTimeDesc": "按剩余时间降序", + "@remainingTimeDesc": {}, + "remainingTimeAsc": "按剩余时间升序", + "@remainingTimeAsc": {}, + "durationAsc": "时长由短到长", + "@durationAsc": {}, + "durationDesc": "时长由长到短", + "@durationDesc": {}, + "nameAsc": "标签 A-Z", + "@nameAsc": {}, + "nameDesc": "标签 Z-A", + "@nameDesc": {}, + "timeOfDayAsc": "时间由早到晚", + "@timeOfDayAsc": {}, + "clearFiltersAction": "清除所有过滤器", + "@clearFiltersAction": {}, + "enableAllFilteredAlarmsAction": "启用所有已过滤闹钟", + "@enableAllFilteredAlarmsAction": {}, + "cancelSkipAllFilteredAlarmsAction": "取消跳过所有已过滤闹钟", + "@cancelSkipAllFilteredAlarmsAction": {}, + "skippingDescriptionSuffix": "(下一次已跳过)", + "@skippingDescriptionSuffix": {}, + "alarmDescriptionFinished": "无未来响铃", + "@alarmDescriptionFinished": {}, + "stopwatchPrevious": "上一圈", + "@stopwatchPrevious": {}, + "stopwatchFastest": "最快", + "@stopwatchFastest": {}, + "alarmDescriptionDays": "在 {days}", + "@alarmDescriptionDays": {}, + "stopwatchSlowest": "最慢", + "@stopwatchSlowest": {}, + "stopwatchAverage": "平均", + "@stopwatchAverage": {}, + "defaultSettingGroup": "默认设置", + "@defaultSettingGroup": {}, + "alarmsDefaultSettingGroupDescription": "设置新闹钟默认值", + "@alarmsDefaultSettingGroupDescription": {}, + "alarmDescriptionRange": "从 {startDate} 到 {endDate} {interval, select, daily{每天} weekly{每周} other{其他时间}}响铃", + "@alarmDescriptionRange": {}, + "alarmDescriptionDates": "在 {date}{count, plural, =0{} =1{ 及另外一个日期} other{ 及另外 {count} 日期}}响铃", + "@alarmDescriptionDates": {}, + "showFiltersSetting": "显示过滤器", + "@showFiltersSetting": {}, + "showSortSetting": "显示排序", + "@showSortSetting": {}, + "notificationsSettingGroup": "通知", + "@notificationsSettingGroup": {}, + "showUpcomingAlarmNotificationSetting": "显示将响闹钟通知", + "@showUpcomingAlarmNotificationSetting": {}, + "showSnoozeNotificationSetting": "显示贪睡通知", + "@showSnoozeNotificationSetting": {}, + "presetsSetting": "预设", + "@presetsSetting": {}, + "newPresetPlaceholder": "新预设", + "@newPresetPlaceholder": {}, + "dismissActionSetting": "关闭操作类型", + "@dismissActionSetting": {}, + "dismissActionSlide": "滑动", + "@dismissActionSlide": {}, + "dismissActionButtons": "按钮", + "@dismissActionButtons": {}, + "upcomingLeadTimeSetting": "提前通知时间", + "@upcomingLeadTimeSetting": {}, + "comparisonLapBarsSettingGroup": "圈用时比较条", + "@comparisonLapBarsSettingGroup": {}, + "showPreviousLapSetting": "显示上一圈", + "@showPreviousLapSetting": {}, + "showFastestLapSetting": "显示最快一圈", + "@showFastestLapSetting": {}, + "showAverageLapSetting": "显示平均用时", + "@showAverageLapSetting": {}, + "leftHandedSetting": "左手模式", + "@leftHandedSetting": {}, + "exportSettingsSetting": "导出", + "@exportSettingsSetting": {}, + "exportSettingsSettingDescription": "将设置导出到本地文件", + "@exportSettingsSettingDescription": {}, + "importSettingsSettingDescription": "从本地文件导入设置", + "@importSettingsSettingDescription": {}, + "versionLabel": "版本", + "@versionLabel": {}, + "licenseLabel": "许可证", + "@licenseLabel": {}, + "emailLabel": "电子邮箱", + "@emailLabel": {}, + "donorsSetting": "捐赠者", + "@donorsSetting": {}, + "donateButton": "捐赠", + "@donateButton": {}, + "addLengthSetting": "添加时长", + "@addLengthSetting": {}, + "sameTime": "时间相同", + "@sameTime": {}, + "searchSettingPlaceholder": "搜索设置", + "@searchSettingPlaceholder": {}, + "searchCityPlaceholder": "搜索城市", + "@searchCityPlaceholder": {}, + "cityAlreadyInFavorites": "此城市已被收藏", + "@cityAlreadyInFavorites": {}, + "durationPickerTitle": "选择时长", + "@durationPickerTitle": {}, + "relativeTime": "{relative, select, ahead{早} behind{晚} other{其他}} {hours} 小时", + "@relativeTime": {}, + "wednesdayShort": "三", + "@wednesdayShort": {}, + "thursdayShort": "四", + "@thursdayShort": {}, + "fridayShort": "五", + "@fridayShort": {}, + "saturdayShort": "六", + "@saturdayShort": {}, + "sundayShort": "日", + "@sundayShort": {}, + "mondayLetter": "M", + "@mondayLetter": {}, + "tuesdayLetter": "T", + "@tuesdayLetter": {}, + "wednesdayLetter": "W", + "@wednesdayLetter": {}, + "thursdayLetter": "T", + "@thursdayLetter": {}, + "fridayLetter": "F", + "@fridayLetter": {}, + "saturdayLetter": "S", + "@saturdayLetter": {}, + "sundayLetter": "S", + "@sundayLetter": {}, + "donateDescription": "捐赠以支持本应用开发", + "@donateDescription": {}, + "donorsDescription": "慷慨的赞助商", + "@donorsDescription": {}, + "contributorsDescription": "助力本应用实现的人们", + "@contributorsDescription": {}, + "mathHardDifficulty": "困难 (X × Y + Z)", + "@mathHardDifficulty": {}, + "mathVeryHardDifficulty": "非常困难 (X × Y × Z)", + "@mathVeryHardDifficulty": {}, + "retypeNumberChars": "字符数", + "@retypeNumberChars": {}, + "retypeIncludeNumSetting": "包括数字", + "@retypeIncludeNumSetting": {}, + "noButton": "否", + "@noButton": {}, + "duplicateButton": "创建副本", + "@duplicateButton": {}, + "dismissAlarmButton": "关闭", + "@dismissAlarmButton": {}, + "allFilter": "所有", + "@allFilter": {}, + "dateFilterGroup": "日期", + "@dateFilterGroup": {}, + "logTypeFilterGroup": "类型", + "@logTypeFilterGroup": {}, + "stateFilterGroup": "状态", + "@stateFilterGroup": {}, + "colorSchemeNamePlaceholder": "颜色主题", + "@colorSchemeNamePlaceholder": {}, + "colorSchemeErrorSettingGroup": "错误颜色", + "@colorSchemeErrorSettingGroup": {}, + "styleThemeElevationSetting": "高度", + "@styleThemeElevationSetting": {}, + "styleThemeShadowSettingGroup": "阴影颜色", + "@styleThemeShadowSettingGroup": {}, + "styleThemeOpacitySetting": "透明度", + "@styleThemeOpacitySetting": {}, + "styleThemeBlurSetting": "模糊", + "@styleThemeBlurSetting": {}, + "styleThemeOutlineSettingGroup": "轮廓", + "@styleThemeOutlineSettingGroup": {}, + "maxLogsSetting": "日志上限", + "@maxLogsSetting": {}, + "alarmLogSetting": "闹钟日志", + "@alarmLogSetting": {}, + "colorsSettingGroup": "颜色", + "@colorsSettingGroup": {}, + "soundSettingGroup": "声音", + "@soundSettingGroup": {}, + "reliabilitySettingGroup": "可靠性", + "@reliabilitySettingGroup": {}, + "styleSettingGroup": "样式", + "@styleSettingGroup": {}, + "materialBrightnessSystem": "跟随系统", + "@materialBrightnessSystem": {}, + "materialBrightnessDark": "深色", + "@materialBrightnessDark": {}, + "systemDarkModeSetting": "系统深色模式", + "@systemDarkModeSetting": {}, + "melodySetting": "铃声", + "@melodySetting": {}, + "audioChannelNotification": "通知", + "@audioChannelNotification": {}, + "colorSchemeSetting": "颜色主题", + "@colorSchemeSetting": {}, + "vibrationSetting": "振动", + "@vibrationSetting": {}, + "audioChannelRingtone": "铃声", + "@audioChannelRingtone": {}, + "timerSettingGroup": "计时器", + "@timerSettingGroup": {}, + "selectTime": "选择时间", + "@selectTime": {}, + "cancelButton": "取消", + "@cancelButton": {}, + "customizeButton": "自定义", + "@customizeButton": {}, + "saveButton": "保存", + "@saveButton": {}, + "soundAndVibrationSettingGroup": "声音与振动", + "@soundAndVibrationSettingGroup": {}, + "scheduleTypeField": "类型", + "@scheduleTypeField": {}, + "scheduleTypeOnce": "仅一次", + "@scheduleTypeOnce": {}, + "snoozeLengthSetting": "时长", + "@snoozeLengthSetting": {}, + "maxSnoozesSetting": "最大贪睡次数", + "@maxSnoozesSetting": {}, + "snoozePreventDisablingSetting": "防止禁用", + "@snoozePreventDisablingSetting": {}, + "snoozePreventDeletionSetting": "防止删除", + "@snoozePreventDeletionSetting": {}, + "createdDateFilterGroup": "创建日期", + "@createdDateFilterGroup": {}, + "activeFilter": "活跃", + "@activeFilter": {}, + "disabledFilter": "已禁用", + "@disabledFilter": {}, + "tomorrowFilter": "明天", + "@tomorrowFilter": {}, + "inactiveFilter": "不活跃", + "@inactiveFilter": {}, + "snoozedFilter": "贪睡", + "@snoozedFilter": {}, + "timeOfDayDesc": "时间由晚到早", + "@timeOfDayDesc": {}, + "filterActions": "过滤器操作", + "@filterActions": {}, + "disableAllFilteredAlarmsAction": "禁用所有已过滤闹钟", + "@disableAllFilteredAlarmsAction": {}, + "skipAllFilteredAlarmsAction": "跳过所有已过滤闹钟", + "@skipAllFilteredAlarmsAction": {}, + "deleteAllFilteredAction": "删除所有已过滤闹钟", + "@deleteAllFilteredAction": {}, + "alarmDescriptionSnooze": "贪睡至 {date}", + "@alarmDescriptionSnooze": {}, + "alarmDescriptionNotScheduled": "无计划", + "@alarmDescriptionNotScheduled": {}, + "alarmDescriptionToday": "就在今天", + "@alarmDescriptionToday": {}, + "alarmDescriptionTomorrow": "就在明天", + "@alarmDescriptionTomorrow": {}, + "alarmDescriptionEveryDay": "每天", + "@alarmDescriptionEveryDay": {}, + "alarmDescriptionWeekend": "每周末", + "@alarmDescriptionWeekend": {}, + "alarmDescriptionWeekday": "每个工作日", + "@alarmDescriptionWeekday": {}, + "alarmDescriptionWeekly": "每 {days}", + "@alarmDescriptionWeekly": {}, + "timerDefaultSettingGroupDescription": "设置新计时器默认值", + "@timerDefaultSettingGroupDescription": {}, + "filtersSettingGroup": "过滤器", + "@filtersSettingGroup": {}, + "showNotificationSetting": "显示通知", + "@showNotificationSetting": {}, + "dismissActionAreaButtons": "区域按钮", + "@dismissActionAreaButtons": {}, + "stopwatchTimeFormatSettingGroup": "时间格式", + "@stopwatchTimeFormatSettingGroup": {}, + "stopwatchShowMillisecondsSetting": "显示毫秒", + "@stopwatchShowMillisecondsSetting": {}, + "showSlowestLapSetting": "显示最慢一圈", + "@showSlowestLapSetting": {}, + "importSettingsSetting": "导入", + "@importSettingsSetting": {}, + "packageNameLabel": "软件包名称", + "@packageNameLabel": {}, + "viewOnGithubLabel": "在 GitHub 上查看", + "@viewOnGithubLabel": {}, + "openSourceLicensesSetting": "开放源代码许可", + "@openSourceLicensesSetting": {}, + "contributorsSetting": "贡献者", + "@contributorsSetting": {}, + "wednesdayFull": "星期三", + "@wednesdayFull": {}, + "editButton": "编辑", + "@editButton": {}, + "noLapsMessage": "还没有计圈", + "@noLapsMessage": {}, + "elapsedTime": "总用时", + "@elapsedTime": {}, + "tuesdayFull": "星期二", + "@tuesdayFull": {}, + "thursdayFull": "星期四", + "@thursdayFull": {}, + "mondayFull": "星期一", + "@mondayFull": {}, + "fridayFull": "星期五", + "@fridayFull": {}, + "saturdayFull": "星期六", + "@saturdayFull": {}, + "tuesdayShort": "二", + "@tuesdayShort": {}, + "sundayFull": "星期日", + "@sundayFull": {}, + "mondayShort": "一", + "@mondayShort": {} +} diff --git a/lib/l10n/language_local.dart b/lib/l10n/language_local.dart new file mode 100644 index 00000000..488c8cd4 --- /dev/null +++ b/lib/l10n/language_local.dart @@ -0,0 +1,228 @@ +import 'package:clock_app/settings/types/setting.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:locale_names/locale_names.dart'; + +List getLocaleOptions() { + return AppLocalizations.supportedLocales.map((locale) { + return SelectSettingOption( + (context) => Locale.fromSubtags( + languageCode: locale.languageCode, + scriptCode: locale.scriptCode, + countryCode: locale.countryCode) + .nativeDisplayLanguage, + locale); + }).toList(); +} + +final isoLangs = { + "ab": {"name": "Abkhaz", "nativeName": "аҧсуа"}, + "aa": {"name": "Afar", "nativeName": "Afaraf"}, + "af": {"name": "Afrikaans", "nativeName": "Afrikaans"}, + "ak": {"name": "Akan", "nativeName": "Akan"}, + "sq": {"name": "Albanian", "nativeName": "Shqip"}, + "am": {"name": "Amharic", "nativeName": "አማርኛ"}, + "ar": {"name": "Arabic", "nativeName": "العربية"}, + "an": {"name": "Aragonese", "nativeName": "Aragonés"}, + "hy": {"name": "Armenian", "nativeName": "Հայերեն"}, + "as": {"name": "Assamese", "nativeName": "অসমীয়া"}, + "av": {"name": "Avaric", "nativeName": "авар мацӀ, магӀарул мацӀ"}, + "ae": {"name": "Avestan", "nativeName": "avesta"}, + "ay": {"name": "Aymara", "nativeName": "aymar aru"}, + "az": {"name": "Azerbaijani", "nativeName": "azərbaycan dili"}, + "bm": {"name": "Bambara", "nativeName": "bamanankan"}, + "ba": {"name": "Bashkir", "nativeName": "башҡорт теле"}, + "eu": {"name": "Basque", "nativeName": "euskara, euskera"}, + "be": {"name": "Belarusian", "nativeName": "Беларуская"}, + "bn": {"name": "Bengali", "nativeName": "বাংলা"}, + "bh": {"name": "Bihari", "nativeName": "भोजपुरी"}, + "bi": {"name": "Bislama", "nativeName": "Bislama"}, + "bs": {"name": "Bosnian", "nativeName": "bosanski jezik"}, + "br": {"name": "Breton", "nativeName": "brezhoneg"}, + "bg": {"name": "Bulgarian", "nativeName": "български език"}, + "my": {"name": "Burmese", "nativeName": "ဗမာစာ"}, + "ca": {"name": "Catalan; Valencian", "nativeName": "Català"}, + "ch": {"name": "Chamorro", "nativeName": "Chamoru"}, + "ce": {"name": "Chechen", "nativeName": "нохчийн мотт"}, + "ny": { + "name": "Chichewa; Chewa; Nyanja", + "nativeName": "chiCheŵa, chinyanja" + }, + "zh": {"name": "Chinese", "nativeName": "中文 (Zhōngwén), 汉语, 漢語"}, + "cv": {"name": "Chuvash", "nativeName": "чӑваш чӗлхи"}, + "kw": {"name": "Cornish", "nativeName": "Kernewek"}, + "co": {"name": "Corsican", "nativeName": "corsu, lingua corsa"}, + "cr": {"name": "Cree", "nativeName": "ᓀᐦᐃᔭᐍᐏᐣ"}, + "hr": {"name": "Croatian", "nativeName": "hrvatski"}, + "cs": {"name": "Czech", "nativeName": "česky, čeština"}, + "da": {"name": "Danish", "nativeName": "dansk"}, + "dv": {"name": "Divehi; Dhivehi; Maldivian;", "nativeName": "ދިވެހި"}, + "nl": {"name": "Dutch", "nativeName": "Nederlands, Vlaams"}, + "en": {"name": "English", "nativeName": "English"}, + "eo": {"name": "Esperanto", "nativeName": "Esperanto"}, + "et": {"name": "Estonian", "nativeName": "eesti, eesti keel"}, + "ee": {"name": "Ewe", "nativeName": "Eʋegbe"}, + "fo": {"name": "Faroese", "nativeName": "føroyskt"}, + "fj": {"name": "Fijian", "nativeName": "vosa Vakaviti"}, + "fi": {"name": "Finnish", "nativeName": "suomi, suomen kieli"}, + "fr": {"name": "French", "nativeName": "français, langue française"}, + "ff": { + "name": "Fula; Fulah; Pulaar; Pular", + "nativeName": "Fulfulde, Pulaar, Pular" + }, + "gl": {"name": "Galician", "nativeName": "Galego"}, + "ka": {"name": "Georgian", "nativeName": "ქართული"}, + "de": {"name": "German", "nativeName": "Deutsch"}, + "el": {"name": "Greek, Modern", "nativeName": "Ελληνικά"}, + "gn": {"name": "Guaraní", "nativeName": "Avañeẽ"}, + "gu": {"name": "Gujarati", "nativeName": "ગુજરાતી"}, + "ht": {"name": "Haitian; Haitian Creole", "nativeName": "Kreyòl ayisyen"}, + "ha": {"name": "Hausa", "nativeName": "Hausa, هَوُسَ"}, + "he": {"name": "Hebrew (modern)", "nativeName": "עברית"}, + "hz": {"name": "Herero", "nativeName": "Otjiherero"}, + "hi": {"name": "Hindi", "nativeName": "हिन्दी, हिंदी"}, + "ho": {"name": "Hiri Motu", "nativeName": "Hiri Motu"}, + "hu": {"name": "Hungarian", "nativeName": "Magyar"}, + "ia": {"name": "Interlingua", "nativeName": "Interlingua"}, + "id": {"name": "Indonesian", "nativeName": "Bahasa Indonesia"}, + "ie": { + "name": "Interlingue", + "nativeName": "Originally called Occidental; then Interlingue after WWII" + }, + "ga": {"name": "Irish", "nativeName": "Gaeilge"}, + "ig": {"name": "Igbo", "nativeName": "Asụsụ Igbo"}, + "ik": {"name": "Inupiaq", "nativeName": "Iñupiaq, Iñupiatun"}, + "io": {"name": "Ido", "nativeName": "Ido"}, + "is": {"name": "Icelandic", "nativeName": "Íslenska"}, + "it": {"name": "Italian", "nativeName": "Italiano"}, + "iu": {"name": "Inuktitut", "nativeName": "ᐃᓄᒃᑎᑐᑦ"}, + "ja": {"name": "Japanese", "nativeName": "日本語 (にほんご/にっぽんご)"}, + "jv": {"name": "Javanese", "nativeName": "basa Jawa"}, + "kl": { + "name": "Kalaallisut, Greenlandic", + "nativeName": "kalaallisut, kalaallit oqaasii" + }, + "kn": {"name": "Kannada", "nativeName": "ಕನ್ನಡ"}, + "kr": {"name": "Kanuri", "nativeName": "Kanuri"}, + "ks": {"name": "Kashmiri", "nativeName": "कश्मीरी, كشميري‎"}, + "kk": {"name": "Kazakh", "nativeName": "Қазақ тілі"}, + "km": {"name": "Khmer", "nativeName": "ភាសាខ្មែរ"}, + "ki": {"name": "Kikuyu, Gikuyu", "nativeName": "Gĩkũyũ"}, + "rw": {"name": "Kinyarwanda", "nativeName": "Ikinyarwanda"}, + "ky": {"name": "Kirghiz, Kyrgyz", "nativeName": "кыргыз тили"}, + "kv": {"name": "Komi", "nativeName": "коми кыв"}, + "kg": {"name": "Kongo", "nativeName": "KiKongo"}, + "ko": {"name": "Korean", "nativeName": "한국어 (韓國語), 조선말 (朝鮮語)"}, + "ku": {"name": "Kurdish", "nativeName": "Kurdî, كوردی‎"}, + "kj": {"name": "Kwanyama, Kuanyama", "nativeName": "Kuanyama"}, + "la": {"name": "Latin", "nativeName": "latine, lingua latina"}, + "lb": { + "name": "Luxembourgish, Letzeburgesch", + "nativeName": "Lëtzebuergesch" + }, + "lg": {"name": "Luganda", "nativeName": "Luganda"}, + "li": {"name": "Limburgish, Limburgan, Limburger", "nativeName": "Limburgs"}, + "ln": {"name": "Lingala", "nativeName": "Lingála"}, + "lo": {"name": "Lao", "nativeName": "ພາສາລາວ"}, + "lt": {"name": "Lithuanian", "nativeName": "lietuvių kalba"}, + "lu": {"name": "Luba-Katanga", "nativeName": ""}, + "lv": {"name": "Latvian", "nativeName": "latviešu valoda"}, + "gv": {"name": "Manx", "nativeName": "Gaelg, Gailck"}, + "mk": {"name": "Macedonian", "nativeName": "македонски јазик"}, + "mg": {"name": "Malagasy", "nativeName": "Malagasy fiteny"}, + "ms": {"name": "Malay", "nativeName": "bahasa Melayu, بهاس ملايو‎"}, + "ml": {"name": "Malayalam", "nativeName": "മലയാളം"}, + "mt": {"name": "Maltese", "nativeName": "Malti"}, + "mi": {"name": "Māori", "nativeName": "te reo Māori"}, + "mr": {"name": "Marathi (Marāṭhī)", "nativeName": "मराठी"}, + "mh": {"name": "Marshallese", "nativeName": "Kajin M̧ajeļ"}, + "mn": {"name": "Mongolian", "nativeName": "монгол"}, + "na": {"name": "Nauru", "nativeName": "Ekakairũ Naoero"}, + "nv": {"name": "Navajo, Navaho", "nativeName": "Diné bizaad, Dinékʼehǰí"}, + "nb_NO": {"name": "Norwegian Bokmål", "nativeName": "Norsk bokmål"}, + "nd": {"name": "North Ndebele", "nativeName": "isiNdebele"}, + "ne": {"name": "Nepali", "nativeName": "नेपाली"}, + "ng": {"name": "Ndonga", "nativeName": "Owambo"}, + "nn": {"name": "Norwegian Nynorsk", "nativeName": "Norsk nynorsk"}, + "no": {"name": "Norwegian", "nativeName": "Norsk"}, + "ii": {"name": "Nuosu", "nativeName": "ꆈꌠ꒿ Nuosuhxop"}, + "nr": {"name": "South Ndebele", "nativeName": "isiNdebele"}, + "oc": {"name": "Occitan", "nativeName": "Occitan"}, + "oj": {"name": "Ojibwe, Ojibwa", "nativeName": "ᐊᓂᔑᓈᐯᒧᐎᓐ"}, + "cu": { + "name": + "Old Church Slavonic, Church Slavic, Church Slavonic, Old Bulgarian, Old Slavonic", + "nativeName": "ѩзыкъ словѣньскъ" + }, + "om": {"name": "Oromo", "nativeName": "Afaan Oromoo"}, + "or": {"name": "Oriya", "nativeName": "ଓଡ଼ିଆ"}, + "os": {"name": "Ossetian, Ossetic", "nativeName": "ирон æвзаг"}, + "pa": {"name": "Panjabi, Punjabi", "nativeName": "ਪੰਜਾਬੀ, پنجابی‎"}, + "pi": {"name": "Pāli", "nativeName": "पाऴि"}, + "fa": {"name": "Persian", "nativeName": "فارسی"}, + "pl": {"name": "Polish", "nativeName": "polski"}, + "ps": {"name": "Pashto, Pushto", "nativeName": "پښتو"}, + "pt": {"name": "Portuguese", "nativeName": "Português"}, + "qu": {"name": "Quechua", "nativeName": "Runa Simi, Kichwa"}, + "rm": {"name": "Romansh", "nativeName": "rumantsch grischun"}, + "rn": {"name": "Kirundi", "nativeName": "kiRundi"}, + "ro": {"name": "Romanian, Moldavian, Moldovan", "nativeName": "română"}, + "ru": {"name": "Russian", "nativeName": "русский язык"}, + "sa": {"name": "Sanskrit (Saṁskṛta)", "nativeName": "संस्कृतम्"}, + "sc": {"name": "Sardinian", "nativeName": "sardu"}, + "sd": {"name": "Sindhi", "nativeName": "सिन्धी, سنڌي، سندھی‎"}, + "se": {"name": "Northern Sami", "nativeName": "Davvisámegiella"}, + "sm": {"name": "Samoan", "nativeName": "gagana faa Samoa"}, + "sg": {"name": "Sango", "nativeName": "yângâ tî sängö"}, + "sr": {"name": "Serbian", "nativeName": "српски језик"}, + "gd": {"name": "Scottish Gaelic; Gaelic", "nativeName": "Gàidhlig"}, + "sn": {"name": "Shona", "nativeName": "chiShona"}, + "si": {"name": "Sinhala, Sinhalese", "nativeName": "සිංහල"}, + "sk": {"name": "Slovak", "nativeName": "slovenčina"}, + "sl": {"name": "Slovene", "nativeName": "slovenščina"}, + "so": {"name": "Somali", "nativeName": "Soomaaliga, af Soomaali"}, + "st": {"name": "Southern Sotho", "nativeName": "Sesotho"}, + "es": {"name": "Spanish; Castilian", "nativeName": "español, castellano"}, + "su": {"name": "Sundanese", "nativeName": "Basa Sunda"}, + "sw": {"name": "Swahili", "nativeName": "Kiswahili"}, + "ss": {"name": "Swati", "nativeName": "SiSwati"}, + "sv": {"name": "Swedish", "nativeName": "svenska"}, + "ta": {"name": "Tamil", "nativeName": "தமிழ்"}, + "te": {"name": "Telugu", "nativeName": "తెలుగు"}, + "tg": {"name": "Tajik", "nativeName": "тоҷикӣ, toğikī, تاجیکی‎"}, + "th": {"name": "Thai", "nativeName": "ไทย"}, + "ti": {"name": "Tigrinya", "nativeName": "ትግርኛ"}, + "bo": {"name": "Tibetan Standard, Tibetan, Central", "nativeName": "བོད་ཡིག"}, + "tk": {"name": "Turkmen", "nativeName": "Türkmen, Түркмен"}, + "tl": {"name": "Tagalog", "nativeName": "Wikang Tagalog, ᜏᜒᜃᜅ᜔ ᜆᜄᜎᜓᜄ᜔"}, + "tn": {"name": "Tswana", "nativeName": "Setswana"}, + "to": {"name": "Tonga (Tonga Islands)", "nativeName": "faka Tonga"}, + "tr": {"name": "Turkish", "nativeName": "Türkçe"}, + "ts": {"name": "Tsonga", "nativeName": "Xitsonga"}, + "tt": {"name": "Tatar", "nativeName": "татарча, tatarça, تاتارچا‎"}, + "tw": {"name": "Twi", "nativeName": "Twi"}, + "ty": {"name": "Tahitian", "nativeName": "Reo Tahiti"}, + "ug": {"name": "Uighur, Uyghur", "nativeName": "Uyƣurqə, ئۇيغۇرچە‎"}, + "uk": {"name": "Ukrainian", "nativeName": "українська"}, + "ur": {"name": "Urdu", "nativeName": "اردو"}, + "uz": {"name": "Uzbek", "nativeName": "zbek, Ўзбек, أۇزبېك‎"}, + "ve": {"name": "Venda", "nativeName": "Tshivenḓa"}, + "vi": {"name": "Vietnamese", "nativeName": "Tiếng Việt"}, + "vo": {"name": "Volapük", "nativeName": "Volapük"}, + "wa": {"name": "Walloon", "nativeName": "Walon"}, + "cy": {"name": "Welsh", "nativeName": "Cymraeg"}, + "wo": {"name": "Wolof", "nativeName": "Wollof"}, + "fy": {"name": "Western Frisian", "nativeName": "Frysk"}, + "xh": {"name": "Xhosa", "nativeName": "isiXhosa"}, + "yi": {"name": "Yiddish", "nativeName": "ייִדיש"}, + "yo": {"name": "Yoruba", "nativeName": "Yorùbá"}, + "za": {"name": "Zhuang, Chuang", "nativeName": "Saɯ cueŋƅ, Saw cuengh"} +}; + +Map? getlanguageDisplayName(String key) { + if (isoLangs.containsKey(key)) { + return isoLangs[key]; + } else { + throw Exception("Language key incorrect"); + } +} diff --git a/lib/navigation/data/fullscreen_intent.dart b/lib/navigation/data/fullscreen_intent.dart new file mode 100644 index 00000000..faa0c3f9 --- /dev/null +++ b/lib/navigation/data/fullscreen_intent.dart @@ -0,0 +1 @@ +const fullscreenIntentKey = "fullscreen_intent"; diff --git a/lib/navigation/data/tabs.dart b/lib/navigation/data/tabs.dart index 472ba9a3..dd70ab1a 100644 --- a/lib/navigation/data/tabs.dart +++ b/lib/navigation/data/tabs.dart @@ -5,13 +5,18 @@ import 'package:clock_app/timer/screens/timer_screen.dart'; import 'package:clock_app/icons/flux_icons.dart'; import 'package:clock_app/clock/screens/clock_screen.dart'; import 'package:clock_app/navigation/types/tab.dart'; +import 'package:flutter/material.dart' hide Tab; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -final List tabs = [ - Tab(title: 'Alarm', icon: FluxIcons.alarm, widget: const AlarmScreen()), - Tab(title: 'Clock', icon: FluxIcons.clock, widget: const ClockScreen()), - Tab(title: 'Timer', icon: FluxIcons.timer, widget: const TimerScreen()), + +List getTabs(BuildContext context) { + return [ + Tab(title: AppLocalizations.of(context)!.alarmTitle, icon: FluxIcons.alarm, widget: const AlarmScreen()), + Tab(title: AppLocalizations.of(context)!.clockTitle, icon: FluxIcons.clock, widget: const ClockScreen()), + Tab(title: AppLocalizations.of(context)!.timerTitle, icon: FluxIcons.timer, widget: const TimerScreen()), Tab( - title: 'Stopwatch', + title: AppLocalizations.of(context)!.stopwatchTitle, icon: FluxIcons.stopwatch, widget: const StopwatchScreen()), ]; +} diff --git a/lib/navigation/screens/nav_scaffold.dart b/lib/navigation/screens/nav_scaffold.dart index f07983d2..654fde84 100644 --- a/lib/navigation/screens/nav_scaffold.dart +++ b/lib/navigation/screens/nav_scaffold.dart @@ -2,9 +2,11 @@ import 'dart:async'; import 'package:clock_app/alarm/logic/new_alarm_snackbar.dart'; import 'package:clock_app/alarm/types/alarm.dart'; +import 'package:clock_app/common/data/app_info.dart'; import 'package:clock_app/common/utils/snackbar.dart'; import 'package:clock_app/icons/flux_icons.dart'; import 'package:clock_app/navigation/data/tabs.dart'; +import 'package:clock_app/navigation/types/tab.dart'; import 'package:clock_app/navigation/widgets/app_navigation_bar.dart'; import 'package:clock_app/navigation/widgets/app_top_bar.dart'; import 'package:clock_app/settings/data/general_settings_schema.dart'; @@ -14,6 +16,7 @@ import 'package:clock_app/settings/types/setting.dart'; import 'package:clock_app/system/logic/handle_intents.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:home_widget/home_widget.dart'; import 'package:receive_intent/receive_intent.dart' as intent_handler; class NavScaffold extends StatefulWidget { @@ -114,16 +117,19 @@ class _NavScaffoldState extends State { @override Widget build(BuildContext context) { Orientation orientation = MediaQuery.of(context).orientation; + final tabs = getTabs(context); return Scaffold( appBar: orientation == Orientation.portrait ? AppTopBar( - title: Text(tabs[_selectedTabIndex].title, - style: Theme.of(context).textTheme.titleMedium?.copyWith( - color: Theme.of(context) - .colorScheme - .onBackground - .withOpacity(0.6), - )), + title: Text( + tabs[_selectedTabIndex].title, + style: Theme.of(context).textTheme.titleMedium?.copyWith( + color: Theme.of(context) + .colorScheme + .onBackground + .withOpacity(0.6), + ), + ), actions: [ IconButton( onPressed: () { @@ -164,7 +170,6 @@ class _NavScaffoldState extends State { .onBackground .withOpacity(0.6), )), - trailing: IconButton( onPressed: () { ScaffoldMessenger.of(context).removeCurrentSnackBar(); diff --git a/lib/navigation/types/app_visibility.dart b/lib/navigation/types/app_visibility.dart index d68ec1a7..069a7774 100644 --- a/lib/navigation/types/app_visibility.dart +++ b/lib/navigation/types/app_visibility.dart @@ -1,7 +1,8 @@ import 'dart:async'; +import 'package:clock_app/common/utils/list_storage.dart'; +import 'package:clock_app/navigation/data/fullscreen_intent.dart'; import 'package:flutter_fgbg/flutter_fgbg.dart'; -import 'package:get_storage/get_storage.dart'; class AppVisibility { static StreamSubscription? subscription; @@ -15,12 +16,11 @@ class AppVisibility { } static void initialize() { - if (GetStorage().read("fullScreenNotificationRecentlyShown") == - true) { - GetStorage().write("fullScreenNotificationRecentlyShown", false); - } else { + // if (loadTextFileSync(fullscreenIntentKey) == "true") { + // saveTextFile(fullscreenIntentKey, "false"); + // } else { setState(FGBGType.foreground); - } + // } subscription = FGBGEvents.stream.listen((event) { setState(event); diff --git a/lib/navigation/widgets/app_navigation_bar.dart b/lib/navigation/widgets/app_navigation_bar.dart index 83bd437b..808f3aef 100644 --- a/lib/navigation/widgets/app_navigation_bar.dart +++ b/lib/navigation/widgets/app_navigation_bar.dart @@ -1,8 +1,9 @@ import 'package:clock_app/common/widgets/card_container.dart'; import 'package:clock_app/navigation/data/tabs.dart'; +import 'package:clock_app/navigation/types/tab.dart'; import 'package:clock_app/navigation/widgets/nav_bar.dart'; import 'package:clock_app/navigation/widgets/nav_bar_item.dart'; -import 'package:flutter/material.dart'; +import 'package:flutter/material.dart' hide Tab; class AppNavigationBar extends StatefulWidget { final int selectedTabIndex; @@ -16,8 +17,12 @@ class AppNavigationBar extends StatefulWidget { } class _AppNavigationBarState extends State { + + @override Widget build(BuildContext context) { + List tabs = getTabs(context); + return Padding( padding: const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 4.0, top: 0), diff --git a/lib/notifications/logic/notification_callbacks.dart b/lib/notifications/logic/notification_callbacks.dart index b56137a9..faacc9a3 100644 --- a/lib/notifications/logic/notification_callbacks.dart +++ b/lib/notifications/logic/notification_callbacks.dart @@ -1,13 +1,7 @@ import 'package:awesome_notifications/awesome_notifications.dart'; -import 'package:clock_app/alarm/logic/alarm_reminder_notifications.dart'; -import 'package:clock_app/alarm/logic/update_alarms.dart'; -import 'package:clock_app/alarm/types/alarm.dart'; -import 'package:clock_app/alarm/utils/alarm_id.dart'; -import 'package:clock_app/common/types/notification_type.dart'; import 'package:clock_app/notifications/data/notification_channel.dart'; import 'package:clock_app/notifications/types/fullscreen_notification_data.dart'; import 'package:clock_app/notifications/types/fullscreen_notification_manager.dart'; -import 'package:clock_app/settings/data/settings_schema.dart'; import 'package:clock_app/stopwatch/logic/update_stopwatch.dart'; import 'package:clock_app/system/logic/initialize_isolate.dart'; import 'package:clock_app/timer/logic/update_timers.dart'; diff --git a/lib/notifications/types/fullscreen_notification_manager.dart b/lib/notifications/types/fullscreen_notification_manager.dart index 7bce2bb1..86d12ee1 100644 --- a/lib/notifications/types/fullscreen_notification_manager.dart +++ b/lib/notifications/types/fullscreen_notification_manager.dart @@ -8,21 +8,25 @@ import 'package:clock_app/alarm/logic/alarm_isolate.dart'; import 'package:clock_app/alarm/logic/update_alarms.dart'; import 'package:clock_app/app.dart'; import 'package:clock_app/common/types/notification_type.dart'; +import 'package:clock_app/common/utils/list_storage.dart'; +import 'package:clock_app/navigation/data/fullscreen_intent.dart'; import 'package:clock_app/notifications/data/notification_channel.dart'; import 'package:clock_app/alarm/logic/schedule_alarm.dart'; import 'package:clock_app/navigation/types/app_visibility.dart'; import 'package:clock_app/navigation/types/routes.dart'; import 'package:clock_app/notifications/types/fullscreen_notification_data.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_fgbg/flutter_fgbg.dart'; import 'package:flutter_show_when_locked/flutter_show_when_locked.dart'; import 'package:get_storage/get_storage.dart'; import 'package:move_to_background/move_to_background.dart'; +import 'package:receive_intent/receive_intent.dart'; class AlarmNotificationManager { static const String _snoozeActionKey = "snooze"; static const String _dismissActionKey = "dismiss"; - static FGBGType _appVisibilityWhenCreated = FGBGType.foreground; + static FGBGType appVisibilityWhenCreated = FGBGType.foreground; static void showFullScreenNotification({ required ScheduledNotificationType type, @@ -98,22 +102,29 @@ class AlarmNotificationManager { static Future closeNotification(ScheduledNotificationType type) async { await removeNotification(type); - await GetStorage.init(); - // await LockScreenFlagManager.clearLockScreenFlags(); await FlutterShowWhenLocked().hide(); - // If we were on the alarm screen, pop it off the stack. Sometimes the system - // decides to show a heads up notification instead of a full screen one, so - // we can't always pop the top screen. - Routes.popIf(alarmNotificationData[type]?.route); - // If notification was created while app was in background, move app back // to background when we close the notification - if (_appVisibilityWhenCreated == FGBGType.background && + + if (appVisibilityWhenCreated == FGBGType.background && AppVisibility.state == FGBGType.foreground) { MoveToBackground.moveTaskToBack(); } - GetStorage().write("fullScreenNotificationRecentlyShown", false); + + // try { + // final receivedIntent = await ReceiveIntent.getInitialIntent(); + // print("reeeeeeeeeeeeeeeeeeeeeeeeeee ${receivedIntent}"); + // // Validate receivedIntent and warn the user, if it is not correct, + // // but keep in mind it could be `null` or "empty"(`receivedIntent.isNull`). + // } on PlatformException { + // // Handle exception + // } + + // If we were on the alarm screen, pop it off the stack. Sometimes the system + // decides to show a heads up notification instead of a full screen one, so + // we can't always pop the top screen. + Routes.popIf(alarmNotificationData[type]?.route); } static Future snoozeAlarm( @@ -149,7 +160,6 @@ class AlarmNotificationManager { break; } await closeNotification(type); - } static Future stopAlarm(int scheduleId, ScheduledNotificationType type, @@ -162,8 +172,7 @@ class AlarmNotificationManager { } static void handleNotificationCreated(ReceivedNotification notification) { - _appVisibilityWhenCreated = AppVisibility.state; - GetStorage().write("fullScreenNotificationRecentlyShown", false); + // _appVisibilityWhenCreated = AppVisibility.state; } static Future openNotificationScreen( @@ -197,7 +206,7 @@ class AlarmNotificationManager { (json.decode((payload['scheduleIds'])!) as List).cast(); if (scheduleIds.isEmpty) return; - if (tasksRequired && dismissType != AlarmDismissType.snooze){ + if (tasksRequired && dismissType != AlarmDismissType.snooze) { await openNotificationScreen(data, scheduleIds, tasksOnly: true, dismissType: dismissType); } else { @@ -223,7 +232,10 @@ class AlarmNotificationManager { break; default: + /* print("ahsan is the besttttttttttttttttttttt ${AppVisibility.state}"); */ + await openNotificationScreen(data, scheduleIds); + break; } } diff --git a/lib/settings/data/accessibility_settings_schema.dart b/lib/settings/data/accessibility_settings_schema.dart index 2ece8449..8acfc0eb 100644 --- a/lib/settings/data/accessibility_settings_schema.dart +++ b/lib/settings/data/accessibility_settings_schema.dart @@ -1,10 +1,15 @@ import 'package:clock_app/settings/types/setting.dart'; import 'package:clock_app/settings/types/setting_group.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; SettingGroup accessibilitySettingsSchema = SettingGroup( "Accessibility", - [SwitchSetting("Left Handed Mode", false)], + (context) => AppLocalizations.of(context)!.accessibilitySettingGroup, + [ + SwitchSetting("Left Handed Mode", + (context) => AppLocalizations.of(context)!.leftHandedSetting, false) + ], icon: Icons.accessibility_new_rounded, showExpandedView: false, ); diff --git a/lib/settings/data/alarm_app_settings_schema.dart b/lib/settings/data/alarm_app_settings_schema.dart index 2fb5591d..1d05e86c 100644 --- a/lib/settings/data/alarm_app_settings_schema.dart +++ b/lib/settings/data/alarm_app_settings_schema.dart @@ -9,70 +9,87 @@ import 'package:clock_app/settings/types/setting_enable_condition.dart'; import 'package:clock_app/settings/types/setting_group.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; SettingGroup alarmAppSettingsSchema = SettingGroup( "Alarm", + (context) => AppLocalizations.of(context)!.alarmTitle, [ SettingGroup( "Default Settings", + (context) => AppLocalizations.of(context)!.defaultSettingGroup, [...alarmSettingsSchema.settingItems], - description: "Set default settings for new alarms", + getDescription: (context) => + AppLocalizations.of(context)!.alarmsDefaultSettingGroupDescription, icon: Icons.settings, ), - SelectSetting("Dismiss Action Type", searchTags: [ - "action", - "buttons", - "slider", - "slide", - "area" - ], [ - SelectSettingOption( - "Slide", - NotificationAction( - builder: (onDismiss, onSnooze, dismissLabel, snoozeLabel) => - SlideNotificationAction( - onDismiss: onDismiss, - onSnooze: onSnooze, - dismissLabel: dismissLabel, - snoozeLabel: snoozeLabel, + SelectSetting( + "Dismiss Action Type", + (context) => AppLocalizations.of(context)!.dismissActionSetting, + searchTags: [ + "action", + "buttons", + "slider", + "slide", + "area" + ], + [ + SelectSettingOption( + (context) => AppLocalizations.of(context)!.dismissActionSlide, + NotificationAction( + builder: (onDismiss, onSnooze, dismissLabel, snoozeLabel) => + SlideNotificationAction( + onDismiss: onDismiss, + onSnooze: onSnooze, + dismissLabel: dismissLabel, + snoozeLabel: snoozeLabel, + ), + ), ), - ), - ), - SelectSettingOption( - "Buttons", - NotificationAction( - builder: (onDismiss, onSnooze, dismissLabel, snoozeLabel) => - ButtonsNotificationAction( - onDismiss: onDismiss, - onSnooze: onSnooze, - dismissLabel: dismissLabel, - snoozeLabel: snoozeLabel, - ), - ), - ), - SelectSettingOption( - "Area Buttons", - NotificationAction( - builder: (onDismiss, onSnooze, dismissLabel, snoozeLabel) => - AreaNotificationAction( - onDismiss: onDismiss, - onSnooze: onSnooze, - dismissLabel: dismissLabel, - snoozeLabel: snoozeLabel, + SelectSettingOption( + (context) => AppLocalizations.of(context)!.dismissActionButtons, + NotificationAction( + builder: (onDismiss, onSnooze, dismissLabel, snoozeLabel) => + ButtonsNotificationAction( + onDismiss: onDismiss, + onSnooze: onSnooze, + dismissLabel: dismissLabel, + snoozeLabel: snoozeLabel, + ), + ), ), - ), - ) - ]), - SettingGroup("Filters", [ - SwitchSetting("Show Filters", true), - SwitchSetting("Show Sort", true), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.dismissActionAreaButtons, + NotificationAction( + builder: (onDismiss, onSnooze, dismissLabel, snoozeLabel) => + AreaNotificationAction( + onDismiss: onDismiss, + onSnooze: onSnooze, + dismissLabel: dismissLabel, + snoozeLabel: snoozeLabel, + ), + ), + ) + ]), + SettingGroup("Filters", + (context) => AppLocalizations.of(context)!.filtersSettingGroup, [ + SwitchSetting("Show Filters", + (context) => AppLocalizations.of(context)!.showFiltersSetting, true), + SwitchSetting("Show Sort", + (context) => AppLocalizations.of(context)!.showSortSetting, true), ]), SettingGroup( "Notifications", + (context) => AppLocalizations.of(context)!.notificationsSettingGroup, [ - SwitchSetting("Show Upcoming Alarm Notifications", true), + SwitchSetting( + "Show Upcoming Alarm Notifications", + (context) => AppLocalizations.of(context)! + .showUpcomingAlarmNotificationSetting, + true), SliderSetting( "Upcoming Lead Time", + (context) => AppLocalizations.of(context)!.upcomingLeadTimeSetting, 5, 120, 10, @@ -83,7 +100,11 @@ SettingGroup alarmAppSettingsSchema = SettingGroup( ["Show Upcoming Alarm Notifications"], (value) => value), ], ), - SwitchSetting("Show Snooze Notifications", true), + SwitchSetting( + "Show Snooze Notifications", + (context) => + AppLocalizations.of(context)!.showSnoozeNotificationSetting, + true), ], ) ], diff --git a/lib/settings/data/appearance_settings_schema.dart b/lib/settings/data/appearance_settings_schema.dart index a70eec39..b4a8bd38 100644 --- a/lib/settings/data/appearance_settings_schema.dart +++ b/lib/settings/data/appearance_settings_schema.dart @@ -9,6 +9,7 @@ import 'package:clock_app/theme/types/color_scheme.dart'; import 'package:clock_app/theme/types/style_theme.dart'; import 'package:clock_app/theme/utils/color_scheme.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; enum ThemeBrightness { light, dark, system } @@ -16,22 +17,36 @@ enum DarkMode { user, system, nightDay } SettingGroup appearanceSettingsSchema = SettingGroup( "Appearance", + (context) => AppLocalizations.of(context)!.appearanceSettingGroup, [ SettingGroup( "Colors", + (context) => AppLocalizations.of(context)!.colorsSettingGroup, [ SwitchSetting( "Use Material You", + (context) => AppLocalizations.of(context)!.useMaterialYouColorSetting, false, onChange: (context, value) => App.refreshTheme(context), searchTags: ["primary", "color", "material"], ), SelectSetting( "Brightness", + (context) => + AppLocalizations.of(context)!.materialBrightnessSetting, [ - SelectSettingOption("System", ThemeBrightness.system), - SelectSettingOption("Light", ThemeBrightness.light), - SelectSettingOption("Dark", ThemeBrightness.dark), + SelectSettingOption( + (context) => + AppLocalizations.of(context)!.materialBrightnessSystem, + ThemeBrightness.system), + SelectSettingOption( + (context) => + AppLocalizations.of(context)!.materialBrightnessLight, + ThemeBrightness.light), + SelectSettingOption( + (context) => + AppLocalizations.of(context)!.materialBrightnessDark, + ThemeBrightness.dark), ], enableConditions: [ ValueCondition(["Use Material You"], (value) => value == true) @@ -39,6 +54,7 @@ SettingGroup appearanceSettingsSchema = SettingGroup( onChange: (context, index) => {App.refreshTheme(context)}), SwitchSetting( "System Dark Mode", + (context) => AppLocalizations.of(context)!.systemDarkModeSetting, false, enableConditions: [ ValueCondition(["Use Material You"], (value) => value == false) @@ -46,8 +62,10 @@ SettingGroup appearanceSettingsSchema = SettingGroup( onChange: (context, value) => {App.refreshTheme(context)}), CustomSetting( "Color Scheme", - description: - "Select from predefined color schemes or create your own", + (context) => AppLocalizations.of(context)!.colorSchemeSetting, + + // description: + // "Select from predefined color schemes or create your own", defaultColorScheme, (context, setting) => ThemesScreen( saveTag: 'color_schemes', @@ -71,8 +89,9 @@ SettingGroup appearanceSettingsSchema = SettingGroup( ), CustomSetting( "Dark Color Scheme", - description: - "Select from predefined color schemes or create your own", + (context) => AppLocalizations.of(context)!.darkColorSchemeSetting, + // description: + // "Select from predefined color schemes or create your own", defaultDarkColorScheme, (context, setting) => ThemesScreen( saveTag: 'color_schemes', @@ -92,11 +111,12 @@ SettingGroup appearanceSettingsSchema = SettingGroup( searchTags: ["theme", "style", "visual", "dark mode", "night mode"], enableConditions: [ ValueCondition(["Use Material You"], (value) => value == false), - ValueCondition(["System Dark Mode"],(value) => value==true) + ValueCondition(["System Dark Mode"], (value) => value == true) ], ), SwitchSetting( "Override Accent Color", + (context) => AppLocalizations.of(context)!.overrideAccentSetting, false, onChange: (context, value) { App.refreshTheme(context); @@ -106,23 +126,28 @@ SettingGroup appearanceSettingsSchema = SettingGroup( // ValueCondition(["Use Material You"], (value) => value == false) ], ), - ColorSetting("Accent Color", Colors.cyan, onChange: (context, color) { - App.refreshTheme(context); - }, enableConditions: [ - ValueCondition(["Override Accent Color"], (value) => value == true), - // ValueCondition(["Use Material You"], (value) => value == false) - ], searchTags: [ - "primary", - "color", - "material you" - ]), + ColorSetting( + "Accent Color", + (context) => AppLocalizations.of(context)!.accentColorSetting, + Colors.cyan, + onChange: (context, color) { + App.refreshTheme(context); + }, + enableConditions: [ + ValueCondition(["Override Accent Color"], (value) => value == true), + // ValueCondition(["Use Material You"], (value) => value == false) + ], + searchTags: ["primary", "color", "material you"], + ), ], ), SettingGroup( "Style", + (context) => AppLocalizations.of(context)!.styleSettingGroup, [ SwitchSetting( "Use Material Style", + (context) => AppLocalizations.of(context)!.useMaterialStyleSetting, false, onChange: (context, value) => App.refreshTheme(context), searchTags: [ @@ -141,7 +166,8 @@ SettingGroup appearanceSettingsSchema = SettingGroup( ), CustomSetting( "Style Theme", - description: "Change styles like shadows, outlines and opacities", + (context) => AppLocalizations.of(context)!.styleThemeSetting, + // description: "Change styles like shadows, outlines and opacities", defaultStyleTheme, (context, setting) => ThemesScreen( saveTag: 'style_themes', @@ -174,5 +200,6 @@ SettingGroup appearanceSettingsSchema = SettingGroup( ), ], icon: Icons.palette_outlined, - description: "Set themes, colors and change layout", + getDescription: (context) => + AppLocalizations.of(context)!.appearanceSettingGroupDescription, ); diff --git a/lib/settings/data/backup_settings_schema.dart b/lib/settings/data/backup_settings_schema.dart index c10e7d44..f34fcc90 100644 --- a/lib/settings/data/backup_settings_schema.dart +++ b/lib/settings/data/backup_settings_schema.dart @@ -6,39 +6,49 @@ import 'package:clock_app/app.dart'; import 'package:clock_app/settings/data/settings_schema.dart'; import 'package:clock_app/settings/types/setting_action.dart'; import 'package:clock_app/settings/types/setting_group.dart'; +import 'package:clock_app/widgets/logic/update_widgets.dart'; import 'package:flutter/material.dart'; import 'package:pick_or_save/pick_or_save.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; SettingGroup backupSettingsSchema = SettingGroup( "Backup", - description: "Export or Import your settings locally", + (context) => AppLocalizations.of(context)!.backupSettingGroup, + getDescription: (context) => + AppLocalizations.of(context)!.backupSettingGroupDescription, icon: Icons.restore_rounded, [ SettingGroup( "Settings", + (context) => AppLocalizations.of(context)!.backupSettingGroup, [ SettingAction( "Export", + (context) => AppLocalizations.of(context)!.exportSettingsSetting, (context) async { saveBackupFile(json.encode(appSettings.valueToJson()), "settings"); }, searchTags: ["settings", "export", "backup", "save"], - description: "Export settings to a local file", + getDescription: (context) => + AppLocalizations.of(context)!.exportSettingsSettingDescription, ), SettingAction( "Import", + (context) => AppLocalizations.of(context)!.importSettingsSetting, (context) async { loadBackupFile( - (data) { + (data) async { appSettings.loadValueFromJson(json.decode(data)); appSettings.callAllListeners(); App.refreshTheme(context); - appSettings.save(); + await appSettings.save(); + if (context.mounted) setDigitalClockWidgetData(context); }, ); }, searchTags: ["settings", "import", "backup", "load"], - description: "Import settings from a local file", + getDescription: (context) => + AppLocalizations.of(context)!.importSettingsSettingDescription, ), ], ), diff --git a/lib/settings/data/developer_settings_schema.dart b/lib/settings/data/developer_settings_schema.dart index 0c3dcc97..e32d7770 100644 --- a/lib/settings/data/developer_settings_schema.dart +++ b/lib/settings/data/developer_settings_schema.dart @@ -4,27 +4,37 @@ import 'package:clock_app/settings/types/setting_group.dart'; import 'package:clock_app/settings/types/setting_link.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; SettingGroup developerSettingsSchema = SettingGroup( "Developer Options", + (context) => AppLocalizations.of(context)!.developerOptionsSettingGroup, [ - SettingGroup("Alarm", [ + SettingGroup("Alarm", + (context) => AppLocalizations.of(context)!.alarmTitle, + [ SwitchSetting( "Show Instant Alarm Button", + (context) => AppLocalizations.of(context)!.showIstantAlarmButtonSetting, kDebugMode, - description: - "Show a button on the alarm screen that creates an alarm that rings one second in the future", + // description: + // "Show a button on the alarm screen that creates an alarm that rings one second in the future", ), ]), - SettingGroup("Logs", [ + SettingGroup("Logs", + (context) => AppLocalizations.of(context)!.logsSettingGroup, + [ SliderSetting( "Max logs", + (context) => AppLocalizations.of(context)!.maxLogsSetting, 10, 500, 100, snapLength: 1, ), - SettingPageLink("Alarm Logs", const AlarmEventsScreen()), + SettingPageLink("Alarm Logs", + (context) => AppLocalizations.of(context)!.alarmLogSetting, + const AlarmEventsScreen()), ]), ], icon: Icons.code_rounded, diff --git a/lib/settings/data/general_settings_schema.dart b/lib/settings/data/general_settings_schema.dart index 59d26e47..d15675a2 100644 --- a/lib/settings/data/general_settings_schema.dart +++ b/lib/settings/data/general_settings_schema.dart @@ -1,21 +1,27 @@ +import 'dart:io'; + import 'package:app_settings/app_settings.dart'; import 'package:auto_start_flutter/auto_start_flutter.dart'; +import 'package:clock_app/app.dart'; import 'package:clock_app/clock/types/time.dart'; import 'package:clock_app/common/utils/list_storage.dart'; import 'package:clock_app/common/utils/snackbar.dart'; import 'package:clock_app/common/utils/time_format.dart'; import 'package:clock_app/icons/flux_icons.dart'; +import 'package:clock_app/l10n/language_local.dart'; import 'package:clock_app/settings/screens/ringtones_screen.dart'; import 'package:clock_app/settings/screens/tags_screen.dart'; import 'package:clock_app/settings/types/setting.dart'; import 'package:clock_app/settings/types/setting_action.dart'; import 'package:clock_app/settings/types/setting_group.dart'; import 'package:clock_app/settings/types/setting_link.dart'; +import 'package:clock_app/widgets/logic/update_widgets.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:intl/intl.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; enum TimePickerType { dial, input, spinner } @@ -23,143 +29,198 @@ enum DurationPickerType { rings, spinner } SelectSettingOption _getDateSettingOption(String format) { return SelectSettingOption( - "${DateFormat(format).format(DateTime.now())} ($format)", format); + (context) => "${DateFormat(format).format(DateTime.now())} ($format)", + format); } +final dateFormatOptions = [ + _getDateSettingOption("dd/MM/yyyy"), + _getDateSettingOption("dd-MM-yyyy"), + _getDateSettingOption("d/M/yyyy"), + _getDateSettingOption("d-M-yyyy"), + _getDateSettingOption("MM/dd/yyyy"), + _getDateSettingOption("MM-dd-yyyy"), + _getDateSettingOption("M/d/yy"), + _getDateSettingOption("M-d-yy"), + _getDateSettingOption("M/d/yyyy"), + _getDateSettingOption("M-d-yyyy"), + _getDateSettingOption("yyyy/dd/MM"), + _getDateSettingOption("yyyy-dd-MM"), + _getDateSettingOption("yyyy/MM/dd"), + _getDateSettingOption("yyyy-MM-dd"), + _getDateSettingOption("d MMM yyyy"), + _getDateSettingOption("d MMMM yyyy"), +]; + enum SwipeAction { cardActions, switchTabs, } final timeFormatOptions = [ - SelectSettingOption("12 Hours", TimeFormat.h12), - SelectSettingOption("24 Hours", TimeFormat.h24), - SelectSettingOption("Device Settings", TimeFormat.device), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.timeFormat12, TimeFormat.h12), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.timeFormat24, TimeFormat.h24), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.timeFormatDevice, + TimeFormat.device), ]; SettingGroup generalSettingsSchema = SettingGroup( "General", + (context) => AppLocalizations.of(context)!.generalSettingGroup, [ - SettingGroup("Display", [ - SelectSetting( - "Date Format", - [ - _getDateSettingOption("dd/MM/yyyy"), - _getDateSettingOption("dd-MM-yyyy"), - _getDateSettingOption("d/M/yyyy"), - _getDateSettingOption("d-M-yyyy"), - _getDateSettingOption("MM/dd/yyyy"), - _getDateSettingOption("MM-dd-yyyy"), - _getDateSettingOption("M/d/yy"), - _getDateSettingOption("M-d-yy"), - _getDateSettingOption("M/d/yyyy"), - _getDateSettingOption("M-d-yyyy"), - _getDateSettingOption("yyyy/dd/MM"), - _getDateSettingOption("yyyy-dd-MM"), - _getDateSettingOption("yyyy/MM/dd"), - _getDateSettingOption("yyyy-MM-dd"), - // SelectSettingOption(DateTime.now().toIso8601Date(), "YYYY-MM-DD"), - _getDateSettingOption("d MMM yyyy"), - _getDateSettingOption("d MMMM yyyy"), - ], - description: "How to display the dates", - ), - SelectSetting("Time Format", timeFormatOptions, - description: "12 or 24 hour time", onChange: (context, index) { - saveTextFile("time_format_string", - getTimeFormatString(context, timeFormatOptions[index].value)); - }), - SwitchSetting("Show Seconds", true), - SelectSetting("Time Picker", [ - SelectSettingOption( - "Dial", - TimePickerType.dial, - ), - SelectSettingOption( - "Input", - TimePickerType.input, - ), - SelectSettingOption( - "Spinner", - TimePickerType.spinner, - ), - ], searchTags: [ - "time", - "picker", - "dial", - "input", - "spinner", - ]), - SelectSetting("Duration Picker", [ - SelectSettingOption( - "Rings", - DurationPickerType.rings, + SelectSetting( + "Language", + (context) => AppLocalizations.of(context)!.languageSetting, + [ + SelectSettingOption((context) => AppLocalizations.of(context)!.system, + Locale(Platform.localeName.split("_").first)), + ...getLocaleOptions() + ], + onChange: (context, index) { + App.refreshTheme(context); + }, + ), + SettingGroup( + "Display", + (context) => AppLocalizations.of(context)!.displaySettingGroup, + [ + SelectSetting( + "Date Format", + (context) => AppLocalizations.of(context)!.dateFormatSetting, + dateFormatOptions, + getDescription: (context) => "How to display the dates", + onChange: (context, index) async { + // await HomeWidget.saveWidgetData( + // "dateFormat", dateFormatOptions[index].value); + // updateDigitalClockWidget(); + }, ), - SelectSettingOption( - "Spinner", - DurationPickerType.spinner, + SelectSetting( + "Time Format", + (context) => AppLocalizations.of(context)!.timeFormatSetting, + timeFormatOptions, + getDescription: (context) => "12 or 24 hour time", + onChange: (context, index) async { + String timeFormat = + getTimeFormatString(context, timeFormatOptions[index].value); + saveTextFile("time_format_string", timeFormat); + setDigitalClockWidgetData(context); + }, ), - ], searchTags: [ - "duration", - "rings", - "time", - "picker", - "dial", - "input", - "spinner", - ]), - ]), + SwitchSetting( + "Show Seconds", + (context) => AppLocalizations.of(context)!.showSecondsSetting, + true), + SelectSetting("Time Picker", + (context) => AppLocalizations.of(context)!.timePickerSetting, [ + SelectSettingOption( + (context) => AppLocalizations.of(context)!.pickerDial, + TimePickerType.dial, + ), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.pickerInput, + TimePickerType.input, + ), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.pickerSpinner, + TimePickerType.spinner, + ), + ], + searchTags: [ + "time", + "picker", + "dial", + "input", + "spinner", + ]), + SelectSetting("Duration Picker", + (context) => AppLocalizations.of(context)!.durationPickerSetting, [ + SelectSettingOption( + (context) => AppLocalizations.of(context)!.pickerRings, + DurationPickerType.rings, + ), + SelectSettingOption( + (context) => AppLocalizations.of(context)!.pickerSpinner, + DurationPickerType.spinner, + ), + ], + searchTags: [ + "duration", + "rings", + "time", + "picker", + "dial", + "input", + "spinner", + ]), + ], + ), SelectSetting( "Swipe Action", + (context) => AppLocalizations.of(context)!.swipeActionSetting, [ SelectSettingOption( - "Card Actions", + (context) => AppLocalizations.of(context)!.swipActionCardAction, SwipeAction.cardActions, - description: "Swipe cards to delete or duplicate them", + getDescription: (context) => + AppLocalizations.of(context)!.swipeActionCardActionDescription, ), SelectSettingOption( - "Switch Tabs", + (context) => AppLocalizations.of(context)!.swipActionSwitchTabs, SwipeAction.switchTabs, - description: "Swipe from one tab to the next", + getDescription: (context) => + AppLocalizations.of(context)!.swipeActionSwitchTabsDescription, ) ], ), SettingPageLink( "Melodies", + (context) => AppLocalizations.of(context)!.melodiesSetting, const RingtonesScreen(), searchTags: ["ringtones", "music", "audio", "tones", "custom"], icon: Icons.music_note_outlined, ), SettingPageLink( "Tags", + (context) => AppLocalizations.of(context)!.tagsSetting, const TagsScreen(), searchTags: ["tags", "groups", "filter"], icon: Icons.label_outline_rounded, ), - SettingGroup("Reliability", [ + SettingGroup("Reliability", + (context) => AppLocalizations.of(context)!.reliabilitySettingGroup, [ SettingAction( "Vendor Specific", + (context) => AppLocalizations.of(context)!.vendorSetting, (context) => launchUrl(Uri.parse("https://dontkillmyapp.com")), - description: "Manually disable vendor-specific optimizations", + getDescription: (context) => + AppLocalizations.of(context)!.vendorSettingDescription, ), SettingAction( "Disable Battery Optimization", + (context) => AppLocalizations.of(context)!.batteryOptimizationSetting, (context) async { AppSettings.openAppSettings( type: AppSettingsType.batteryOptimization); }, - description: - "Disable battery optimization for this app to prevent alarms from being delayed", + getDescription: (context) => + AppLocalizations.of(context)!.batteryOptimizationSettingDescription, ), SettingAction( "Allow Notifications", + (context) => AppLocalizations.of(context)!.allowNotificationSetting, (context) async { AppSettings.openAppSettings(type: AppSettingsType.notification); }, - description: "Allow lock screen notifications for alarms and timers", + getDescription: (context) => + AppLocalizations.of(context)!.allowNotificationSettingDescription, ), SettingAction( "Auto Start", + (context) => AppLocalizations.of(context)!.autoStartSetting, (context) async { try { //check auto-start availability. @@ -178,13 +239,15 @@ SettingGroup generalSettingsSchema = SettingGroup( if (kDebugMode) print(e.message); } }, - description: - "Some devices require Auto Start to be enabled for alarms to ring while app is closed.", + getDescription: (context) => + AppLocalizations.of(context)!.autoStartSettingDescription, ), ]), - SettingGroup("Animations", [ + SettingGroup("Animations", + (context) => AppLocalizations.of(context)!.animationSettingGroup, [ SliderSetting( "Animation Speed", + (context) => AppLocalizations.of(context)!.animationSpeedSetting, 0.5, 2, 1, @@ -195,9 +258,13 @@ SettingGroup generalSettingsSchema = SettingGroup( // ["Show Upcoming Alarm Notifications"], (value) => value), // ], ), - SwitchSetting("Extra Animations", false), + SwitchSetting( + "Extra Animations", + (context) => AppLocalizations.of(context)!.extraAnimationSetting, + false), ]) ], icon: FluxIcons.settings, - description: "Set app wide settings like time format", + getDescription: (context) => + AppLocalizations.of(context)!.generalSettingGroupDescription, ); diff --git a/lib/settings/data/localized_names.dart b/lib/settings/data/localized_names.dart new file mode 100644 index 00000000..06845ff6 --- /dev/null +++ b/lib/settings/data/localized_names.dart @@ -0,0 +1,29 @@ +// import 'package:flutter/material.dart'; +// import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +// +// String getLocalizedSettingName(String name, BuildContext context) { +// switch (name) { +// case "General": +// return AppLocalizations.of(context)!.generalSettingGroup; +// case "Appearance": +// return AppLocalizations.of(context)!.appearanceSettingGroup; +// case "Alarm": +// return AppLocalizations.of(context)!.alarmTitle; +// case "Timer": +// return AppLocalizations.of(context)!.timerTitle; +// case "Stopwatch": +// return AppLocalizations.of(context)!.stopwatchTitle; +// case "Clock": +// return AppLocalizations.of(context)!.clockTitle; +// case "Developer Options" +// default: +// return name; +// } +// } +// +// String getLocalizedSettingDescription(String name, BuildContext context) { +// switch (name) { +// default: +// return name; +// } +// } diff --git a/lib/settings/data/settings_schema.dart b/lib/settings/data/settings_schema.dart index c0e09ff9..b26375aa 100644 --- a/lib/settings/data/settings_schema.dart +++ b/lib/settings/data/settings_schema.dart @@ -6,14 +6,18 @@ import 'package:clock_app/settings/data/developer_settings_schema.dart'; import 'package:clock_app/settings/data/general_settings_schema.dart'; import 'package:clock_app/settings/data/stopwatch_settings_schema.dart'; import 'package:clock_app/settings/data/timer_app_settings_schema.dart'; +import 'package:clock_app/settings/data/widget_settings_schema.dart'; import 'package:clock_app/settings/screens/about_screen.dart'; import 'package:clock_app/settings/types/setting_group.dart'; import 'package:clock_app/settings/types/setting_link.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -const int settingsSchemaVersion = 3; +const int settingsSchemaVersion = 4; SettingGroup appSettings = SettingGroup( "Settings", + (context) => AppLocalizations.of(context)!.settings, version: settingsSchemaVersion, isSearchable: true, [ @@ -22,12 +26,15 @@ SettingGroup appSettings = SettingGroup( alarmAppSettingsSchema, timerAppSettingsSchema, stopwatchSettingsSchema, + widgetSettingSchema, accessibilitySettingsSchema, backupSettingsSchema, developerSettingsSchema, SettingPageLink( "About", + (context) => AppLocalizations.of(context)!.aboutSettingGroup, const AboutScreen(), + icon: Icons.info_outline_rounded, ), ], ); diff --git a/lib/settings/data/stopwatch_settings_schema.dart b/lib/settings/data/stopwatch_settings_schema.dart index 595c67bc..7e3f5067 100644 --- a/lib/settings/data/stopwatch_settings_schema.dart +++ b/lib/settings/data/stopwatch_settings_schema.dart @@ -3,30 +3,55 @@ import 'package:clock_app/settings/types/setting.dart'; import 'package:clock_app/settings/types/setting_group.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + SettingGroup stopwatchSettingsSchema = SettingGroup( "Stopwatch", + (context) => AppLocalizations.of(context)!.stopwatchTitle, [ SettingGroup( "Time Format", + (context) => + AppLocalizations.of(context)!.stopwatchTimeFormatSettingGroup, [ - SwitchSetting("Show Milliseconds", true), + SwitchSetting( + "Show Milliseconds", + (context) => AppLocalizations.of(context)! + .stopwatchShowMillisecondsSetting, + true), ], - description: "Show comparison laps bars in stopwatch", + // description: "Show comparison laps bars in stopwatch", icon: Icons.settings, searchTags: ["milliseconds"]), SettingGroup( "Comparison Lap Bars", + (context) => AppLocalizations.of(context)!.comparisonLapBarsSettingGroup, [ - SwitchSetting("Show Previous Lap", true), - SwitchSetting("Show Fastest Lap", true), - SwitchSetting("Show Slowest Lap", true), - SwitchSetting("Show Average Lap", true), + SwitchSetting( + "Show Previous Lap", + (context) => AppLocalizations.of(context)!.showPreviousLapSetting, + true), + SwitchSetting( + "Show Fastest Lap", + (context) => AppLocalizations.of(context)!.showFastestLapSetting, + true), + SwitchSetting( + "Show Slowest Lap", + (context) => AppLocalizations.of(context)!.showSlowestLapSetting, + true), + SwitchSetting( + "Show Average Lap", + (context) => AppLocalizations.of(context)!.showAverageLapSetting, + true), ], - description: "Show comparison laps bars in stopwatch", + // description: "Show comparison laps bars in stopwatch", icon: Icons.settings, searchTags: ["fastest", "slowest", "average", "previous"], ), - SwitchSetting("Show Notification", true), + SwitchSetting( + "Show Notification", + (context) => AppLocalizations.of(context)!.showNotificationSetting, + true), ], icon: FluxIcons.stopwatch, ); diff --git a/lib/settings/data/timer_app_settings_schema.dart b/lib/settings/data/timer_app_settings_schema.dart index dfc54a38..d7fbfdb4 100644 --- a/lib/settings/data/timer_app_settings_schema.dart +++ b/lib/settings/data/timer_app_settings_schema.dart @@ -9,66 +9,83 @@ import 'package:clock_app/settings/types/setting_link.dart'; import 'package:clock_app/timer/data/timer_settings_schema.dart'; import 'package:clock_app/timer/screens/presets_screen.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; SettingGroup timerAppSettingsSchema = SettingGroup( "Timer", + (context) => AppLocalizations.of(context)!.timerTitle, [ SettingGroup( "Default Settings", + (context) => AppLocalizations.of(context)!.defaultSettingGroup, [...timerSettingsSchema.settingItems], - description: "Set default settings for new timers", + getDescription: (context) => + AppLocalizations.of(context)!.timerDefaultSettingGroupDescription, icon: Icons.settings, ), - SettingPageLink("Presets", const PresetsScreen()), - SelectSetting("Dismiss Action Type", searchTags: [ - "action", - "buttons", - "slider", - "slide", - "area" - ], [ - SelectSettingOption( - "Area Buttons", - NotificationAction( - builder: (onDismiss, onSnooze, dismissLabel, snoozeLabel) => - AreaNotificationAction( - onDismiss: onDismiss, - onSnooze: onSnooze, - dismissLabel: dismissLabel, - snoozeLabel: snoozeLabel, + SettingPageLink( + "Presets", + (context) => AppLocalizations.of(context)!.presetsSetting, + const PresetsScreen()), + SelectSetting( + "Dismiss Action Type", + (context) => AppLocalizations.of(context)!.dismissActionSetting, + searchTags: [ + "action", + "buttons", + "slider", + "slide", + "area" + ], + [ + SelectSettingOption( + (context) => AppLocalizations.of(context)!.dismissActionSlide, + NotificationAction( + builder: (onDismiss, onSnooze, dismissLabel, snoozeLabel) => + AreaNotificationAction( + onDismiss: onDismiss, + onSnooze: onSnooze, + dismissLabel: dismissLabel, + snoozeLabel: snoozeLabel, + ), + ), ), - ), - ), - SelectSettingOption( - "Slide", - NotificationAction( - builder: (onDismiss, onSnooze, dismissLabel, snoozeLabel) => - SlideNotificationAction( - onDismiss: onDismiss, - onSnooze: onSnooze, - dismissLabel: dismissLabel, - snoozeLabel: snoozeLabel, + SelectSettingOption( + (context) => AppLocalizations.of(context)!.dismissActionButtons, + NotificationAction( + builder: (onDismiss, onSnooze, dismissLabel, snoozeLabel) => + SlideNotificationAction( + onDismiss: onDismiss, + onSnooze: onSnooze, + dismissLabel: dismissLabel, + snoozeLabel: snoozeLabel, + ), + ), ), - ), - ), - SelectSettingOption( - "Buttons", - NotificationAction( - builder: (onDismiss, onSnooze, dismissLabel, snoozeLabel) => - ButtonsNotificationAction( - onDismiss: onDismiss, - onSnooze: onSnooze, - dismissLabel: dismissLabel, - snoozeLabel: snoozeLabel, + SelectSettingOption( + (context) => AppLocalizations.of(context)!.dismissActionAreaButtons, + NotificationAction( + builder: (onDismiss, onSnooze, dismissLabel, snoozeLabel) => + ButtonsNotificationAction( + onDismiss: onDismiss, + onSnooze: onSnooze, + dismissLabel: dismissLabel, + snoozeLabel: snoozeLabel, + ), + ), ), - ), - ), + ]), + SettingGroup("Filters", + (context) => AppLocalizations.of(context)!.filtersSettingGroup, [ + SwitchSetting("Show Filters", + (context) => AppLocalizations.of(context)!.showFiltersSetting, true), + SwitchSetting("Show Sort", + (context) => AppLocalizations.of(context)!.showSortSetting, true), ]), - SettingGroup("Filters", [ - SwitchSetting("Show Filters", true), - SwitchSetting("Show Sort", true), - ]), - SwitchSetting("Show Notification", true), + SwitchSetting( + "Show Notification", + (context) => AppLocalizations.of(context)!.showNotificationSetting, + true), ], icon: FluxIcons.timer, ); diff --git a/lib/settings/data/widget_settings_schema.dart b/lib/settings/data/widget_settings_schema.dart new file mode 100644 index 00000000..0f1456f7 --- /dev/null +++ b/lib/settings/data/widget_settings_schema.dart @@ -0,0 +1,117 @@ +import 'package:clock_app/settings/types/setting.dart'; +import 'package:clock_app/settings/types/setting_enable_condition.dart'; +import 'package:clock_app/settings/types/setting_group.dart'; +import 'package:clock_app/widgets/logic/update_widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:home_widget/home_widget.dart'; + +SettingGroup widgetSettingSchema = SettingGroup( + "Widgets", + (context) => AppLocalizations.of(context)!.widgetsSettingGroup, + [ + SettingGroup( + "Digital Clock", + (context) => AppLocalizations.of(context)!.digitalClockSettingGroup, + [ + SettingGroup( + "Layout", + (context) => AppLocalizations.of(context)!.layoutSettingGroup, + [ + SwitchSetting( + "Show Date", + (context) => AppLocalizations.of(context)!.showDateSetting, + true, + onChange: (context, value) async { + setDigitalClockWidgetData(context); + }, + ), + SliderSetting( + "Time Size", + (context) => AppLocalizations.of(context)!.timeSizeSetting, + 10, + 100, + 100, + onChange: (context, value) async { + setDigitalClockWidgetData(context); + }, + // snapLength: 1, + ), + SliderSetting( + "Date Size", + (context) => AppLocalizations.of(context)!.dateSizeSetting, + 10, + 100, + 25, + onChange: (context, value) async { + setDigitalClockWidgetData(context); + }, + enableConditions: [ + ValueCondition(["Show Date"], (value) => value == true) + ], + // snapLength: 1, + ), + ], + ), + SettingGroup( + "Text", + (context) => AppLocalizations.of(context)!.textSettingGroup, + [ + ColorSetting( + "Color", + (context) => AppLocalizations.of(context)!.colorSetting, + Colors.white, + // enableOpacity: true, + onChange: (context, value) async { + setDigitalClockWidgetData(context); + }, + ), + ], + ), + // SettingGroup( + // "Shadow", + // (context) => + // AppLocalizations.of(context)!.styleThemeShadowSettingGroup, + // [ + // SliderSetting( + // "Elevation", + // (context) => + // AppLocalizations.of(context)!.styleThemeElevationSetting, + // 0, + // 5, + // 1, + // onChange: (context, value) async { + // await HomeWidget.saveWidgetData( + // "shadowElevation", value); + // updateDigitalClockWidget(); + // }, + // ), + // SliderSetting( + // "Blur", + // (context) => AppLocalizations.of(context)!.styleThemeBlurSetting, + // 0, + // 5, + // 1, + // onChange: (context, value) async { + // await HomeWidget.saveWidgetData("shadowBlur", value); + // updateDigitalClockWidget(); + // }, + // ), + // ColorSetting( + // "Color", + // (context) => AppLocalizations.of(context)!.colorSetting, + // Colors.black, + // enableOpacity: true, + // onChange: (context, value) async { + // await HomeWidget.saveWidgetData( + // "shadowColor", '#${value.value.toRadixString(16)}'); + // updateDigitalClockWidget(); + // }, + // ), + // ], + // ), + ], + ), + ], + icon: Icons.widgets_outlined, +); diff --git a/lib/settings/logic/initialize_settings.dart b/lib/settings/logic/initialize_settings.dart index 91711a00..6f1ecdb2 100644 --- a/lib/settings/logic/initialize_settings.dart +++ b/lib/settings/logic/initialize_settings.dart @@ -26,16 +26,9 @@ import 'package:clock_app/timer/types/timer_preset.dart'; import 'package:flutter/foundation.dart'; import 'package:get_storage/get_storage.dart'; - Future _clearSettings() async { - // List timers = await loadList('timers'); - // List alarms = await loadList('alarms'); // We need to remove all scheduled alarms and timers before clearing the data // Otherwise, there would be no way to remove them in the future - - // for (var timer in timers) { - // timer.reset(); - // } await cancelAllAlarms(); await cancelAllTimers(); await GetStorage().erase(); @@ -59,13 +52,10 @@ Future initializeStorage([bool clearSettingsOnDebug = true]) async { // Comment this out after the preferences are cleared if (kDebugMode && clearSettingsOnDebug) await _clearSettings(); - bool? firstLaunch = GetStorage().read('first_launch'); - if (firstLaunch == null) { - // This is used to show alarm and timer edit animations - GetStorage().write('first_alarm_created', false); - GetStorage().write('first_timer_created', false); - } - + // bool? firstLaunch = GetStorage().read('first_launch'); + // if (firstLaunch == null) { + // } + // await initList("alarms", []); await initList("tags", defaultTags); await initList("alarm_events", []); diff --git a/lib/settings/screens/about_screen.dart b/lib/settings/screens/about_screen.dart index c757812a..5c461ffd 100644 --- a/lib/settings/screens/about_screen.dart +++ b/lib/settings/screens/about_screen.dart @@ -1,13 +1,18 @@ import 'package:clock_app/common/data/app_info.dart'; import 'package:clock_app/common/widgets/card_container.dart'; import 'package:clock_app/navigation/widgets/app_top_bar.dart'; +import 'package:clock_app/settings/screens/contributors.dart'; +import 'package:clock_app/settings/screens/donors.dart'; import 'package:clock_app/settings/screens/licenses.dart'; +import 'package:clock_app/settings/types/setting_action.dart'; import 'package:clock_app/settings/types/setting_link.dart'; +import 'package:clock_app/settings/widgets/setting_action_card.dart'; import 'package:clock_app/settings/widgets/setting_page_link_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher_string.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class AboutScreen extends StatelessWidget { const AboutScreen({super.key}); @@ -19,7 +24,7 @@ class AboutScreen extends StatelessWidget { final TextTheme textTheme = theme.textTheme; return Scaffold( appBar: AppTopBar( - title: Text("About", + title: Text(AppLocalizations.of(context)!.aboutSettingGroup, style: textTheme.titleMedium?.copyWith( color: colorScheme.onBackground.withOpacity(0.6), )), @@ -30,23 +35,36 @@ class AboutScreen extends StatelessWidget { child: Column( children: [ const AboutInfo(), - SettingPageLinkCard(setting: SettingPageLink("Credits", const LicensesScreen())), - // CardContainer( - // child: Padding( - // padding: const EdgeInsets.all(16.0), - // child: Column( - // children: [ - // Text( - // "Contributors", - // style: textTheme.headlineMedium?.copyWith( - // color: colorScheme.primary, - // ), - // ), - // // Image.network( - // // "https://avatars.githubusercontent.com/u/41967492?v=4"), - // ], - // )), - // ) + SettingActionCard( + setting: SettingAction( + "Donate", + getDescription: (context) => + AppLocalizations.of(context)!.donateDescription, + (context) => AppLocalizations.of(context)!.donateButton, + (context) => + launchUrl(Uri.parse("https://www.patreon.com/vicolo"))), + ), + SettingPageLinkCard( + setting: SettingPageLink( + "Donors", + getDescription: (context) => + AppLocalizations.of(context)!.donorsDescription, + (context) => AppLocalizations.of(context)!.donorsSetting, + DonorsScreen())), + SettingPageLinkCard( + setting: SettingPageLink( + "Contributors", + getDescription: (context) => + AppLocalizations.of(context)!.contributorsDescription, + (context) => + AppLocalizations.of(context)!.contributorsSetting, + ContributorsScreen())), + SettingPageLinkCard( + setting: SettingPageLink( + "Open Source Licenses", + (context) => AppLocalizations.of(context)! + .openSourceLicensesSetting, + const LicensesScreen())), ], ), ), @@ -103,7 +121,7 @@ class AboutInfo extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Version", + AppLocalizations.of(context)!.versionLabel, style: textTheme.bodyMedium?.copyWith( color: colorScheme.onSurface, ), @@ -133,7 +151,7 @@ class AboutInfo extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Package name", + AppLocalizations.of(context)!.packageNameLabel, style: textTheme.bodyMedium?.copyWith( color: colorScheme.onSurface, ), @@ -168,7 +186,7 @@ class AboutInfo extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "License", + AppLocalizations.of(context)!.licenseLabel, style: textTheme.bodyMedium?.copyWith( color: colorScheme.onSurface, ), @@ -214,7 +232,7 @@ class AboutInfo extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Email", + AppLocalizations.of(context)!.emailLabel, style: textTheme.bodyMedium?.copyWith( color: colorScheme.onSurface, ), @@ -250,7 +268,7 @@ class AboutInfo extends StatelessWidget { ), const SizedBox(width: 16.0), Text( - "View on Github", + AppLocalizations.of(context)!.viewOnGithubLabel, style: textTheme.bodyMedium?.copyWith( color: colorScheme.onBackground, ), diff --git a/lib/settings/screens/contributors.dart b/lib/settings/screens/contributors.dart new file mode 100644 index 00000000..81e751c1 --- /dev/null +++ b/lib/settings/screens/contributors.dart @@ -0,0 +1,85 @@ +import 'dart:convert'; + +import 'package:clock_app/common/widgets/card_container.dart'; +import 'package:clock_app/navigation/widgets/app_top_bar.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:url_launcher/url_launcher.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +Future readGitContributors() async { + final String response = + await rootBundle.loadString('assets/contributors/git.json'); + return await json.decode(response); +} + +class ContributorsScreen extends StatelessWidget { + ContributorsScreen({super.key}); + final Future gitContributors = readGitContributors(); + + @override + Widget build(BuildContext context) { + final ThemeData theme = Theme.of(context); + final ColorScheme colorScheme = theme.colorScheme; + final TextTheme textTheme = theme.textTheme; + return Scaffold( + appBar: AppTopBar( + title: Text(AppLocalizations.of(context)!.contributorsSetting, + style: textTheme.titleMedium?.copyWith( + color: colorScheme.onBackground.withOpacity(0.6), + )), + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0), + child: FutureBuilder( + future: gitContributors, + builder: (context, snapshot) { + if (snapshot.hasData) { + final dynamic contributors = snapshot.data!; + return Column( + children: [ + for (final contributor in contributors) + CardContainer( + onTap: () async { + if (contributor['profile_url'] != null) { + await launchUrl( + Uri.parse(contributor['profile_url'])); + } + }, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + CardContainer( + child: Image( + width: 48, + image: + AssetImage(contributor['avatar_url']), + ), + ), + const SizedBox(width: 8), + Expanded( + child: Text( + contributor['username'], + style: textTheme.headlineMedium, + maxLines: 1, + overflow: TextOverflow.ellipsis, + softWrap: false, + ), + ), + ], + ), + ), + ), + ], + ); + } else { + return const CircularProgressIndicator(); + } + }, + )), + ), + ); + } +} diff --git a/lib/settings/screens/donors.dart b/lib/settings/screens/donors.dart new file mode 100644 index 00000000..2fccc6b4 --- /dev/null +++ b/lib/settings/screens/donors.dart @@ -0,0 +1,84 @@ +import 'dart:convert'; + +import 'package:clock_app/common/widgets/card_container.dart'; +import 'package:clock_app/navigation/widgets/app_top_bar.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +Future readDonors() async { + final String response = + await rootBundle.loadString('assets/patreons/patreons.json'); + return await json.decode(response); +} + +class DonorsScreen extends StatelessWidget { + DonorsScreen({super.key}); + final Future donors = readDonors(); + + @override + Widget build(BuildContext context) { + final ThemeData theme = Theme.of(context); + final ColorScheme colorScheme = theme.colorScheme; + final TextTheme textTheme = theme.textTheme; + return Scaffold( + appBar: AppTopBar( + title: Text(AppLocalizations.of(context)!.donorsSetting, + style: textTheme.titleMedium?.copyWith( + color: colorScheme.onBackground.withOpacity(0.6), + )), + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0), + child: FutureBuilder( + future: donors, + builder: (context, snapshot) { + if (snapshot.hasData) { + final dynamic contributors = snapshot.data!; + return Column( + children: [ + for (final contributor in contributors) + CardContainer( + // onTap: () async { + // if (contributor['profile_url'] != null) { + // await launchUrl( + // Uri.parse(contributor['profile_url'])); + // } + // }, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), + child: Row( + children: [ + // CardContainer( + // child: Image( + // width: 48, + // image: + // AssetImage(contributor['name']), + // ), + // ), + // const SizedBox(width: 8), + Expanded( + child: Text( + contributor['name'], + style: textTheme.headlineMedium, + maxLines: 1, + overflow: TextOverflow.ellipsis, + softWrap: false, + ), + ), + ], + ), + ), + ), + ], + ); + } else { + return const CircularProgressIndicator(); + } + }, + )), + ), + ); + } +} diff --git a/lib/settings/screens/licenses.dart b/lib/settings/screens/licenses.dart index 63a01460..e675d1b7 100644 --- a/lib/settings/screens/licenses.dart +++ b/lib/settings/screens/licenses.dart @@ -1,13 +1,10 @@ -import 'package:clock_app/common/data/app_info.dart'; -import 'package:clock_app/common/widgets/card_container.dart'; import 'package:clock_app/navigation/widgets/app_top_bar.dart'; import 'package:clock_app/oss_licenses.dart'; import 'package:clock_app/settings/types/setting_action.dart'; import 'package:clock_app/settings/widgets/setting_action_card.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:url_launcher/url_launcher.dart'; -import 'package:url_launcher/url_launcher_string.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class LicensesScreen extends StatelessWidget { const LicensesScreen({super.key}); @@ -19,7 +16,7 @@ class LicensesScreen extends StatelessWidget { final TextTheme textTheme = theme.textTheme; return Scaffold( appBar: AppTopBar( - title: Text("Credits", + title: Text(AppLocalizations.of(context)!.openSourceLicensesSetting, style: textTheme.titleMedium?.copyWith( color: colorScheme.onBackground.withOpacity(0.6), )), @@ -30,7 +27,9 @@ class LicensesScreen extends StatelessWidget { child: Column( children: [ ...allDependencies.map((dependency) => SettingActionCard( - setting: SettingAction(dependency.name, (context) async { + setting: SettingAction(dependency.name, + (context) => dependency.name, + (context) async { if (dependency.repository != null) { await launchUrl(Uri.parse(dependency.repository!)); } diff --git a/lib/settings/screens/restore_defaults_screen.dart b/lib/settings/screens/restore_defaults_screen.dart index 27fb1f26..d9ef2b13 100644 --- a/lib/settings/screens/restore_defaults_screen.dart +++ b/lib/settings/screens/restore_defaults_screen.dart @@ -2,16 +2,14 @@ import 'package:clock_app/common/widgets/card_container.dart'; import 'package:clock_app/navigation/widgets/app_top_bar.dart'; import 'package:clock_app/settings/types/setting_group.dart'; import 'package:clock_app/settings/types/setting_item.dart'; - import 'package:flutter/material.dart'; class SettingCheckBox extends StatelessWidget { const SettingCheckBox( - {Key? key, + {super.key, required this.settingItem, required this.isChecked, - required this.onChanged}) - : super(key: key); + required this.onChanged}); final SettingItem settingItem; @@ -29,7 +27,7 @@ class SettingCheckBox extends StatelessWidget { onChanged: onChanged, ), Text( - settingItem.name, + settingItem.displayName(context), style: Theme.of(context).textTheme.headlineMedium, ), ], @@ -114,7 +112,7 @@ class _RestoreDefaultScreenState extends State { }, ), ) - .toList(), + , const SizedBox(height: 16), ], ), diff --git a/lib/settings/screens/settings_group_screen.dart b/lib/settings/screens/settings_group_screen.dart index 544e040b..e647bbcf 100644 --- a/lib/settings/screens/settings_group_screen.dart +++ b/lib/settings/screens/settings_group_screen.dart @@ -4,7 +4,7 @@ import 'package:clock_app/settings/screens/restore_defaults_screen.dart'; import 'package:clock_app/settings/types/setting_group.dart'; import 'package:clock_app/settings/types/setting_item.dart'; import 'package:clock_app/settings/types/setting_link.dart'; - +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:clock_app/settings/widgets/search_setting_card.dart'; import 'package:clock_app/settings/widgets/setting_page_link_card.dart'; import 'package:clock_app/settings/widgets/settings_top_bar.dart'; @@ -39,6 +39,7 @@ class _SettingGroupScreenState extends State { return Scaffold( appBar: SettingsTopBar( + title: widget.settingGroup.displayName(context), onSearch: (settingItems) { setState(() { searchedItems = settingItems; @@ -66,6 +67,8 @@ class _SettingGroupScreenState extends State { SettingPageLinkCard( setting: SettingPageLink( 'Restore default values', + (context) => AppLocalizations.of(context)! + .restoreSettingGroup, RestoreDefaultScreen( settingGroup: widget.settingGroup, onRestore: () async { diff --git a/lib/settings/types/setting.dart b/lib/settings/types/setting.dart index 93c09d6b..a69d2e81 100644 --- a/lib/settings/types/setting.dart +++ b/lib/settings/types/setting.dart @@ -1,9 +1,11 @@ import 'package:clock_app/common/types/json.dart'; import 'package:clock_app/common/types/list_item.dart'; +import 'package:clock_app/common/types/popup_action.dart'; import 'package:clock_app/common/utils/json_serialize.dart'; import 'package:clock_app/common/utils/list_item.dart'; import 'package:clock_app/settings/types/setting_enable_condition.dart'; import 'package:clock_app/settings/types/setting_item.dart'; +import 'package:clock_app/settings/utils/description.dart'; import 'package:clock_app/timer/types/time_duration.dart'; import 'package:flutter/material.dart'; @@ -21,7 +23,8 @@ abstract class Setting extends SettingItem { Setting( String name, - String description, + String Function(BuildContext) getLocalizedName, + String Function(BuildContext) description, T defaultValue, this.onChange, List enableConditions, @@ -32,7 +35,8 @@ abstract class Setting extends SettingItem { _defaultValue = valueCopyGetter?.call(defaultValue) ?? defaultValue, changesEnableCondition = false, _valueCopyGetter = valueCopyGetter, - super(name, description, searchTags, enableConditions); + super( + name, getLocalizedName, description, searchTags, enableConditions); void setValue(BuildContext context, T value) { _value = _valueCopyGetter?.call(value) ?? value; @@ -65,7 +69,7 @@ abstract class Setting extends SettingItem { class ListSetting extends Setting> { List possibleItems; - Widget Function(T item, [VoidCallback?,VoidCallback?]) cardBuilder; + Widget Function(T item, [VoidCallback?, VoidCallback?]) cardBuilder; Widget Function(T item) addCardBuilder; Widget Function(T item)? itemPreviewBuilder; // The widget that will be used to display the value of this setting. @@ -74,20 +78,22 @@ class ListSetting extends Setting> { ListSetting( String name, + String Function(BuildContext) getLocalizedName, List defaultValue, this.possibleItems, { required this.cardBuilder, required this.valueDisplayBuilder, required this.addCardBuilder, this.itemPreviewBuilder, - String description = "", + String Function(BuildContext) getDescription = defaultDescription, void Function(BuildContext, List)? onChange, bool isVisual = true, List enableConditions = const [], List searchTags = const [], }) : super( name, - description, + getLocalizedName, + getDescription, copyItemList(defaultValue), onChange, enableConditions, @@ -100,12 +106,13 @@ class ListSetting extends Setting> { ListSetting copy() { return ListSetting( name, + getLocalizedName, _value, possibleItems, valueDisplayBuilder: valueDisplayBuilder, cardBuilder: cardBuilder, addCardBuilder: addCardBuilder, - description: description, + getDescription: getDescription, onChange: onChange, enableConditions: enableConditions, isVisual: isVisual, @@ -122,8 +129,9 @@ class ListSetting extends Setting> { return addCardBuilder(item); } - Widget getItemCard(T item, {VoidCallback? onDelete, VoidCallback? onDuplicate}) { - return cardBuilder(item,onDelete,onDuplicate); + Widget getItemCard(T item, + {VoidCallback? onDelete, VoidCallback? onDuplicate}) { + return cardBuilder(item, onDelete, onDuplicate); } Widget? getPreviewCard(T item) { @@ -151,17 +159,18 @@ class CustomSetting extends Setting { CustomSetting( String name, + String Function(BuildContext) getLocalizedName, T defaultValue, this.screenBuilder, this.valueDisplayBuilder, { - String description = "", + String Function(BuildContext) getDescription = defaultDescription, void Function(BuildContext, T)? onChange, this.copyValue, bool isVisual = true, List enableConditions = const [], List searchTags = const [], - }) : super(name, description, defaultValue, onChange, enableConditions, - searchTags, isVisual) { + }) : super(name, getLocalizedName, getDescription, defaultValue, onChange, + enableConditions, searchTags, isVisual) { copyValue ??= (T value) => value; } @@ -177,10 +186,11 @@ class CustomSetting extends Setting { CustomSetting copy() { return CustomSetting( name, + getLocalizedName, copyValue?.call(_value) ?? _value, screenBuilder, valueDisplayBuilder, - description: description, + getDescription: getDescription, onChange: onChange, enableConditions: enableConditions, isVisual: isVisual, @@ -204,22 +214,24 @@ class CustomSetting extends Setting { class SwitchSetting extends Setting { SwitchSetting( String name, + String Function(BuildContext) getLocalizedName, bool defaultValue, { void Function(BuildContext, bool)? onChange, - String description = "", + String Function(BuildContext) getDescription = defaultDescription, bool isVisual = true, List enableConditions = const [], List searchTags = const [], - }) : super(name, description, defaultValue, onChange, enableConditions, - searchTags, isVisual); + }) : super(name, getLocalizedName, getDescription, defaultValue, onChange, + enableConditions, searchTags, isVisual); @override SwitchSetting copy() { return SwitchSetting( name, + getLocalizedName, _value, onChange: onChange, - description: description, + getDescription: getDescription, enableConditions: enableConditions, isVisual: isVisual, searchTags: searchTags, @@ -230,22 +242,24 @@ class SwitchSetting extends Setting { class NumberSetting extends Setting { NumberSetting( String name, + String Function(BuildContext) getLocalizedName, double defaultValue, { void Function(BuildContext, double)? onChange, - String description = "", + String Function(BuildContext) getDescription = defaultDescription, bool isVisual = true, List enableConditions = const [], List searchTags = const [], - }) : super(name, description, defaultValue, onChange, enableConditions, - searchTags, isVisual); + }) : super(name, getLocalizedName, getDescription, defaultValue, onChange, + enableConditions, searchTags, isVisual); @override NumberSetting copy() { return NumberSetting( name, + getLocalizedName, _value, onChange: onChange, - description: description, + getDescription: getDescription, enableConditions: enableConditions, isVisual: isVisual, searchTags: searchTags, @@ -254,16 +268,20 @@ class NumberSetting extends Setting { } class ColorSetting extends Setting { + final bool enableOpacity; + ColorSetting( String name, + String Function(BuildContext) getLocalizedName, Color defaultValue, { void Function(BuildContext, Color)? onChange, - String description = "", + String Function(BuildContext) getDescription = defaultDescription, bool isVisual = true, + this.enableOpacity = false, List enableConditions = const [], List searchTags = const [], - }) : super(name, description, defaultValue, onChange, enableConditions, - searchTags, isVisual); + }) : super(name, getLocalizedName, getDescription, defaultValue, onChange, + enableConditions, searchTags, isVisual); @override dynamic valueToJson() { @@ -280,12 +298,14 @@ class ColorSetting extends Setting { ColorSetting copy() { return ColorSetting( name, + getLocalizedName, _value, onChange: onChange, - description: description, + getDescription: getDescription, enableConditions: enableConditions, isVisual: isVisual, searchTags: searchTags, + enableOpacity: enableOpacity, ); } } @@ -293,22 +313,24 @@ class ColorSetting extends Setting { class StringSetting extends Setting { StringSetting( String name, + String Function(BuildContext) getLocalizedName, String defaultValue, { void Function(BuildContext, String)? onChange, - String description = "", + String Function(BuildContext) getDescription = defaultDescription, bool isVisual = true, List enableConditions = const [], List searchTags = const [], - }) : super(name, description, defaultValue, onChange, enableConditions, - searchTags, isVisual); + }) : super(name, getLocalizedName, getDescription, defaultValue, onChange, + enableConditions, searchTags, isVisual); @override StringSetting copy() { return StringSetting( name, + getLocalizedName, _value, onChange: onChange, - description: description, + getDescription: getDescription, enableConditions: enableConditions, isVisual: isVisual, searchTags: searchTags, @@ -325,19 +347,20 @@ class SliderSetting extends Setting { SliderSetting( String name, + String Function(BuildContext) getLocalizedName, this.min, this.max, double defaultValue, { void Function(BuildContext context, double)? onChange, - String description = "", + String Function(BuildContext) getDescription = defaultDescription, bool isVisual = true, this.maxIsInfinity = false, this.snapLength, this.unit = "", List enableConditions = const [], List searchTags = const [], - }) : super(name, description, defaultValue, onChange, enableConditions, - searchTags, isVisual); + }) : super(name, getLocalizedName, getDescription, defaultValue, onChange, + enableConditions, searchTags, isVisual); // @override // dynamic get value => @@ -347,11 +370,12 @@ class SliderSetting extends Setting { SliderSetting copy() { return SliderSetting( name, + getLocalizedName, min, max, _value, onChange: onChange, - description: description, + getDescription: getDescription, snapLength: snapLength, maxIsInfinity: maxIsInfinity, enableConditions: enableConditions, @@ -364,6 +388,7 @@ class SliderSetting extends Setting { class SelectSetting extends Setting { final List> _options; + final List actions; List> get options => _options; int get selectedIndex => _value; @@ -388,27 +413,31 @@ class SelectSetting extends Setting { SelectSetting( String name, + String Function(BuildContext) getLocalizedName, this._options, { void Function(BuildContext, int)? onChange, int defaultValue = 0, - String description = "", + String Function(BuildContext) getDescription = defaultDescription, bool isVisual = true, List enableConditions = const [], List searchTags = const [], - }) : super(name, description, defaultValue, onChange, enableConditions, - searchTags, isVisual); + this.actions = const [], + }) : super(name, getLocalizedName, getDescription, defaultValue, onChange, + enableConditions, searchTags, isVisual); @override SelectSetting copy() { return SelectSetting( name, + getLocalizedName, _options, defaultValue: _value, onChange: onChange, - description: description, + getDescription: getDescription, enableConditions: enableConditions, isVisual: isVisual, searchTags: searchTags, + actions: actions, ); } } @@ -417,6 +446,7 @@ class SelectSetting extends Setting { // This is so that if the options changes, the value remains the same; class DynamicSelectSetting extends Setting { List> Function() optionsGetter; + final List actions; List> get options => optionsGetter(); @override dynamic get value => options[selectedIndex].value; @@ -424,15 +454,17 @@ class DynamicSelectSetting extends Setting { DynamicSelectSetting( String name, + String Function(BuildContext) getLocalizedName, this.optionsGetter, { void Function(BuildContext, int)? onChange, - String description = "", + String Function(BuildContext) getDescription = defaultDescription, int defaultValue = -1, bool isVisual = true, List enableConditions = const [], List searchTags = const [], - }) : super(name, description, defaultValue, onChange, enableConditions, - searchTags, isVisual) { + this.actions = const [], + }) : super(name, getLocalizedName, getDescription, defaultValue, onChange, + enableConditions, searchTags, isVisual) { if (defaultValue != -1) { _value = defaultValue; } @@ -442,13 +474,15 @@ class DynamicSelectSetting extends Setting { DynamicSelectSetting copy() { return DynamicSelectSetting( name, + getLocalizedName, optionsGetter, onChange: onChange, defaultValue: _value, - description: description, + getDescription: getDescription, enableConditions: enableConditions, isVisual: isVisual, searchTags: searchTags, + actions: actions, ); } @@ -494,6 +528,7 @@ class DynamicSelectSetting extends Setting { class MultiSelectSetting extends Setting> { final List> _options; + final List actions; List> get options => _options; List get selectedIndices => _value; @@ -521,31 +556,35 @@ class MultiSelectSetting extends Setting> { MultiSelectSetting( String name, + String Function(BuildContext) getLocalizedName, this._options, { void Function(BuildContext, List)? onChange, List defaultValue = const [0], - String description = "", + String Function(BuildContext) getDescription = defaultDescription, bool isVisual = true, List enableConditions = const [], List searchTags = const [], - }) : super(name, description, defaultValue, onChange, enableConditions, - searchTags, isVisual); + this.actions = const [], + }) : super(name, getLocalizedName, getDescription, defaultValue, onChange, + enableConditions, searchTags, isVisual); @override MultiSelectSetting copy() { return MultiSelectSetting( name, + getLocalizedName, _options, defaultValue: _value, onChange: onChange, - description: description, + getDescription: getDescription, enableConditions: enableConditions, isVisual: isVisual, searchTags: searchTags, + actions: actions, ); } - @override + @override dynamic valueToJson() { return _value; } @@ -561,25 +600,31 @@ class MultiSelectSetting extends Setting> { // This is so that if the options changes, the value remains the same; class DynamicMultiSelectSetting extends Setting> { List> Function() optionsGetter; + final List actions; List> get options => optionsGetter(); @override dynamic get value { return selectedIndices.map((index) => options[index].value).toList(); -} - List get selectedIndices => - _value.map((id) => getIndexOfId(id)).where((index)=>index>=0).toList(); + } + + List get selectedIndices => _value + .map((id) => getIndexOfId(id)) + .where((index) => index >= 0) + .toList(); DynamicMultiSelectSetting( String name, + String Function(BuildContext) getLocalizedName, this.optionsGetter, { void Function(BuildContext, List)? onChange, - String description = "", + String Function(BuildContext) getDescription = defaultDescription, List defaultValue = const [-1], bool isVisual = true, List enableConditions = const [], List searchTags = const [], - }) : super(name, description, defaultValue, onChange, enableConditions, - searchTags, isVisual) { + this.actions = const [], + }) : super(name, getLocalizedName, getDescription, defaultValue, onChange, + enableConditions, searchTags, isVisual) { if (!defaultValue.contains(-1)) { _value = defaultValue; } @@ -587,13 +632,18 @@ class DynamicMultiSelectSetting extends Setting> { @override DynamicMultiSelectSetting copy() { - return DynamicMultiSelectSetting(name, optionsGetter, - onChange: onChange, - defaultValue: _value, - description: description, - enableConditions: enableConditions, - isVisual: isVisual, - searchTags: searchTags); + return DynamicMultiSelectSetting( + name, + getLocalizedName, + optionsGetter, + onChange: onChange, + defaultValue: _value, + getDescription: getDescription, + enableConditions: enableConditions, + isVisual: isVisual, + searchTags: searchTags, + actions: actions, + ); } void setIndex(BuildContext context, List indices) { @@ -624,7 +674,6 @@ class DynamicMultiSelectSetting extends Setting> { @override dynamic valueToJson() { return _value; - } @override @@ -652,16 +701,18 @@ class ToggleSetting extends Setting> { ToggleSetting( String name, + String Function(BuildContext) getLocalizedName, this.options, { void Function(BuildContext, List)? onChange, List defaultValue = const [], - String description = "", + String Function(BuildContext) getDescription = defaultDescription, bool isVisual = true, List enableConditions = const [], List searchTags = const [], }) : super( name, - description, + getLocalizedName, + getDescription, defaultValue.length == options.length ? List.from(defaultValue) : List.generate(options.length, (index) => index == 0), @@ -676,10 +727,11 @@ class ToggleSetting extends Setting> { ToggleSetting copy() { return ToggleSetting( name, + getLocalizedName, options, defaultValue: _value, onChange: onChange, - description: description, + getDescription: getDescription, enableConditions: enableConditions, isVisual: isVisual, searchTags: searchTags, @@ -711,16 +763,18 @@ class DateTimeSetting extends Setting> { DateTimeSetting( String name, + String Function(BuildContext) getLocalizedName, List defaultValue, { this.rangeOnly = false, void Function(BuildContext, List)? onChange, - String description = "", + String Function(BuildContext) getDescription = defaultDescription, bool isVisual = true, List enableConditions = const [], List searchTags = const [], }) : super( name, - description, + getLocalizedName, + getDescription, defaultValue, onChange, enableConditions, @@ -733,10 +787,11 @@ class DateTimeSetting extends Setting> { DateTimeSetting copy() { return DateTimeSetting( name, + getLocalizedName, _value, rangeOnly: rangeOnly, onChange: onChange, - description: description, + getDescription: getDescription, enableConditions: enableConditions, isVisual: isVisual, searchTags: searchTags, @@ -770,22 +825,24 @@ class DateTimeSetting extends Setting> { class DurationSetting extends Setting { DurationSetting( String name, + String Function(BuildContext) getLocalizedName, TimeDuration defaultValue, { void Function(BuildContext, TimeDuration)? onChange, - String description = "", + String Function(BuildContext) getDescription = defaultDescription, bool isVisual = true, List enableConditions = const [], List searchTags = const [], - }) : super(name, description, defaultValue, onChange, enableConditions, - searchTags, isVisual); + }) : super(name, getLocalizedName, getDescription, defaultValue, onChange, + enableConditions, searchTags, isVisual); @override DurationSetting copy() { return DurationSetting( name, + getLocalizedName, _value, onChange: onChange, - description: description, + getDescription: getDescription, enableConditions: enableConditions, isVisual: isVisual, searchTags: searchTags, @@ -805,16 +862,17 @@ class DurationSetting extends Setting { } class ToggleSettingOption { - String name; + String Function(BuildContext) getLocalizedName; T value; - ToggleSettingOption(this.name, this.value); + ToggleSettingOption(this.getLocalizedName, this.value); } class SelectSettingOption { - String name; - String description; + String Function(BuildContext) getDescription; + String Function(BuildContext) getLocalizedName; T value; - SelectSettingOption(this.name, this.value, {this.description = ""}); + SelectSettingOption(this.getLocalizedName, this.value, + {this.getDescription = defaultDescription}); } diff --git a/lib/settings/types/setting_action.dart b/lib/settings/types/setting_action.dart index 1a72d67c..bf45f32d 100644 --- a/lib/settings/types/setting_action.dart +++ b/lib/settings/types/setting_action.dart @@ -1,5 +1,6 @@ import 'package:clock_app/settings/types/setting_enable_condition.dart'; import 'package:clock_app/settings/types/setting_item.dart'; +import 'package:clock_app/settings/utils/description.dart'; import 'package:flutter/material.dart'; class SettingAction extends SettingItem { @@ -7,18 +8,19 @@ class SettingAction extends SettingItem { SettingAction( String name, + String Function(BuildContext) getLocalizedName, this.action, { - String description = "", + String Function(BuildContext) getDescription = defaultDescription, List searchTags = const [], List enableConditions = const [], - }) : super(name, description, searchTags, enableConditions); + }) : super(name, getLocalizedName, getDescription, searchTags, enableConditions); @override SettingAction copy() { - return SettingAction(name, action, - description: description, + return SettingAction(name, getLocalizedName, action, + getDescription: getDescription, searchTags: searchTags, - enableConditions: enableConditions); + enableConditions: enableConditions,); } @override diff --git a/lib/settings/types/setting_group.dart b/lib/settings/types/setting_group.dart index f2185192..4c982b7e 100644 --- a/lib/settings/types/setting_group.dart +++ b/lib/settings/types/setting_group.dart @@ -7,6 +7,7 @@ import 'package:clock_app/settings/types/setting_action.dart'; import 'package:clock_app/settings/types/setting_enable_condition.dart'; import 'package:clock_app/settings/types/setting_item.dart'; import 'package:clock_app/settings/types/setting_link.dart'; +import 'package:clock_app/settings/utils/description.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:get_storage/get_storage.dart'; @@ -36,12 +37,13 @@ class SettingGroup extends SettingItem { SettingGroup( String name, + String Function(BuildContext) getLocalizedName, this._settingItems, { int? version, IconData? icon, List enableConditions = const [], List summarySettings = const [], - String description = "", + String Function(BuildContext) getDescription = defaultDescription, bool? showExpandedView, bool isSearchable = false, List searchTags = const [], @@ -54,7 +56,8 @@ class SettingGroup extends SettingItem { _settingPageLinks = [], _settingActions = [], _version = version, - super(name, description, searchTags, enableConditions) { + super( + name, getLocalizedName, getDescription, searchTags, enableConditions) { for (SettingItem item in _settingItems) { item.parent = this; if (item is Setting) { @@ -82,6 +85,7 @@ class SettingGroup extends SettingItem { SettingGroup copy() { return SettingGroup( name, + getLocalizedName, _settingItems.map((setting) => setting.copy()).toList(), icon: icon, searchTags: searchTags, @@ -90,7 +94,7 @@ class SettingGroup extends SettingItem { isSearchable: isSearchable, showExpandedView: showExpandedView, summarySettings: _summarySettings, - description: description, + getDescription: getDescription, ); } diff --git a/lib/settings/types/setting_item.dart b/lib/settings/types/setting_item.dart index bc882e63..8c34d768 100644 --- a/lib/settings/types/setting_item.dart +++ b/lib/settings/types/setting_item.dart @@ -1,10 +1,13 @@ +import 'package:clock_app/settings/data/localized_names.dart'; import 'package:clock_app/settings/types/setting.dart'; import 'package:clock_app/settings/types/setting_enable_condition.dart'; import 'package:clock_app/settings/types/setting_group.dart'; +import 'package:flutter/material.dart'; abstract class SettingItem { String name; - String description; + String Function(BuildContext) getLocalizedName; + String Function(BuildContext) getDescription; String id; SettingGroup? _parent; final List _settingListeners; @@ -16,11 +19,17 @@ abstract class SettingItem { List enableSettings; // List compoundEnableSettings; + String displayName(BuildContext context) => + getLocalizedName(context); + + String displayDescription(BuildContext context) => + getDescription(context); + bool get isEnabled { for (var enableSetting in enableSettings) { - if(!enableSetting.evaluate()){ - return false; - } + if (!enableSetting.evaluate()) { + return false; + } } return true; @@ -42,8 +51,8 @@ abstract class SettingItem { return path.reversed.toList(); } - SettingItem(this.name, this.description, this.searchTags, - this.enableConditions) + SettingItem( + this.name, this.getLocalizedName, this.getDescription, this.searchTags, this.enableConditions ) : id = name, _settingListeners = [], enableSettings = []; diff --git a/lib/settings/types/setting_link.dart b/lib/settings/types/setting_link.dart index 377042c0..be5d09ec 100644 --- a/lib/settings/types/setting_link.dart +++ b/lib/settings/types/setting_link.dart @@ -1,5 +1,6 @@ import 'package:clock_app/settings/types/setting_enable_condition.dart'; import 'package:clock_app/settings/types/setting_item.dart'; +import 'package:clock_app/settings/utils/description.dart'; import 'package:flutter/material.dart'; class SettingPageLink extends SettingItem { @@ -8,20 +9,26 @@ class SettingPageLink extends SettingItem { SettingPageLink( String name, + String Function(BuildContext) getLocalizedName, this.screen, { - String description = "", + String Function(BuildContext) getDescription = defaultDescription, this.icon, List searchTags = const [], List enableConditions = const [], - }) : super(name, description, searchTags, enableConditions); + }) : super(name, getLocalizedName, getDescription, searchTags, + enableConditions); @override SettingPageLink copy() { - return SettingPageLink(name, screen, - icon: icon, - description: description, - searchTags: searchTags, - enableConditions: enableConditions); + return SettingPageLink( + name, + getLocalizedName, + screen, + icon: icon, + getDescription: getDescription, + searchTags: searchTags, + enableConditions: enableConditions, + ); } @override diff --git a/lib/settings/utils/description.dart b/lib/settings/utils/description.dart new file mode 100644 index 00000000..a122f2a0 --- /dev/null +++ b/lib/settings/utils/description.dart @@ -0,0 +1,5 @@ +import 'package:flutter/material.dart'; + +String defaultDescription(BuildContext context) { + return ""; +} diff --git a/lib/settings/widgets/color_setting_card.dart b/lib/settings/widgets/color_setting_card.dart index 32fbb2a1..6fa68b51 100644 --- a/lib/settings/widgets/color_setting_card.dart +++ b/lib/settings/widgets/color_setting_card.dart @@ -5,11 +5,10 @@ import 'package:flutter/material.dart'; class ColorSettingCard extends StatefulWidget { const ColorSettingCard( - {Key? key, + {super.key, required this.setting, this.showAsCard = false, - this.onChanged}) - : super(key: key); + this.onChanged}); final ColorSetting setting; final bool showAsCard; @@ -23,8 +22,9 @@ class _ColorSettingCardState extends State { @override Widget build(BuildContext context) { ColorField toggleCard = ColorField( - name: widget.setting.name, + name: widget.setting.displayName(context), value: widget.setting.value, + enableOpacity: widget.setting.enableOpacity, onChange: (value) { setState(() { widget.setting.setValue(context, value); diff --git a/lib/settings/widgets/custom_setting_card.dart b/lib/settings/widgets/custom_setting_card.dart index 4cd481aa..a0381e82 100644 --- a/lib/settings/widgets/custom_setting_card.dart +++ b/lib/settings/widgets/custom_setting_card.dart @@ -38,7 +38,7 @@ class _CustomSettingCardState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - widget.setting.name, + widget.setting.displayName(context), style: Theme.of(context).textTheme.headlineMedium, ), const SizedBox(height: 4.0), diff --git a/lib/settings/widgets/date_setting_card.dart b/lib/settings/widgets/date_setting_card.dart index 3b5c8c32..094601f9 100644 --- a/lib/settings/widgets/date_setting_card.dart +++ b/lib/settings/widgets/date_setting_card.dart @@ -9,11 +9,11 @@ class DateSettingCard extends StatefulWidget { final void Function(List)? onChanged; const DateSettingCard({ - Key? key, + super.key, required this.setting, this.showAsCard = false, this.onChanged, - }) : super(key: key); + }); @override State createState() => _DateSettingCardState(); @@ -23,8 +23,8 @@ class _DateSettingCardState extends State { @override Widget build(BuildContext context) { Widget input = DatePickerField( - title: widget.setting.name, - description: widget.setting.description, + title: widget.setting.displayName(context), + description: widget.setting.displayDescription(context), value: widget.setting.value, rangeOnly: widget.setting.rangeOnly, onChanged: (value) { diff --git a/lib/settings/widgets/duration_setting_card.dart b/lib/settings/widgets/duration_setting_card.dart index 73d10674..e1d8f1fe 100644 --- a/lib/settings/widgets/duration_setting_card.dart +++ b/lib/settings/widgets/duration_setting_card.dart @@ -10,11 +10,11 @@ class DurationSettingCard extends StatefulWidget { final void Function(TimeDuration)? onChanged; const DurationSettingCard({ - Key? key, + super.key, required this.setting, this.showAsCard = false, this.onChanged, - }) : super(key: key); + }); @override State createState() => _DurationSettingCardState(); @@ -24,8 +24,8 @@ class _DurationSettingCardState extends State { @override Widget build(BuildContext context) { Widget input = DurationPickerField( - title: widget.setting.name, - description: widget.setting.description, + title: widget.setting.displayName(context), + description: widget.setting.displayDescription(context), value: widget.setting.value, onChange: (value) { setState(() { diff --git a/lib/settings/widgets/dynamic_multi_select_setting_card.dart b/lib/settings/widgets/dynamic_multi_select_setting_card.dart index 53c2cdca..8eab05fe 100644 --- a/lib/settings/widgets/dynamic_multi_select_setting_card.dart +++ b/lib/settings/widgets/dynamic_multi_select_setting_card.dart @@ -26,14 +26,15 @@ class _DynamicMultiSelectSettingCardState @override Widget build(BuildContext context) { SelectField selectWidget = SelectField( - selectedIndices: widget.setting.selectedIndices, + getSelectedIndices: () => widget.setting.selectedIndices, title: widget.setting.name, multiSelect: true, - choices: widget.setting.options + actions: widget.setting.actions, + getChoices: () => widget.setting.options .map((option) => SelectChoice( - name: option.name, + name: option.getLocalizedName(context), value: option.value, - description: option.description)) + description: option.getDescription(context))) .toList(), onChanged: (indices) { setState(() { diff --git a/lib/settings/widgets/dynamic_select_setting_card.dart b/lib/settings/widgets/dynamic_select_setting_card.dart index eb2a3a5f..2510e8cd 100644 --- a/lib/settings/widgets/dynamic_select_setting_card.dart +++ b/lib/settings/widgets/dynamic_select_setting_card.dart @@ -26,13 +26,14 @@ class _DynamicSelectSettingCardState @override Widget build(BuildContext context) { SelectField selectWidget = SelectField( - selectedIndices: [widget.setting.selectedIndex], - title: widget.setting.name, - choices: widget.setting.options + getSelectedIndices: () => [widget.setting.selectedIndex], + title: widget.setting.displayName(context), + actions: widget.setting.actions, + getChoices: () => widget.setting.options .map((option) => SelectChoice( - name: option.name, + name: option.getLocalizedName(context), value: option.value, - description: option.description)) + description: option.getDescription(context))) .toList(), onChanged: (indices) { setState(() { diff --git a/lib/settings/widgets/list_setting_card.dart b/lib/settings/widgets/list_setting_card.dart index 018e3064..a5d4805f 100644 --- a/lib/settings/widgets/list_setting_card.dart +++ b/lib/settings/widgets/list_setting_card.dart @@ -42,7 +42,7 @@ class _ListSettingCardState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - widget.setting.name, + widget.setting.displayName(context), style: Theme.of(context).textTheme.headlineMedium, ), const SizedBox(height: 4.0), diff --git a/lib/settings/widgets/list_setting_screen.dart b/lib/settings/widgets/list_setting_screen.dart index e99d2a7b..af301660 100644 --- a/lib/settings/widgets/list_setting_screen.dart +++ b/lib/settings/widgets/list_setting_screen.dart @@ -56,7 +56,7 @@ class _ListSettingScreenState Widget build(BuildContext context) { return Scaffold( appBar: AppTopBar( - title: Text(widget.setting.name), + title: Text(widget.setting.displayName(context)), ), body: Stack( children: [ @@ -77,7 +77,7 @@ class _ListSettingScreenState }, onModifyList: () => widget.onChanged(context), placeholderText: - "No ${widget.setting.name.toLowerCase()} added yet", + "No ${widget.setting.displayName(context).toLowerCase()} added yet", ), ), ], diff --git a/lib/settings/widgets/multi_select_setting_card.dart b/lib/settings/widgets/multi_select_setting_card.dart index acc48e56..534ca77b 100644 --- a/lib/settings/widgets/multi_select_setting_card.dart +++ b/lib/settings/widgets/multi_select_setting_card.dart @@ -16,21 +16,23 @@ class MultiSelectSettingCard extends StatefulWidget { final bool showAsCard; @override - State> createState() => _MultiSelectSettingCardState(); + State> createState() => + _MultiSelectSettingCardState(); } class _MultiSelectSettingCardState extends State> { @override Widget build(BuildContext context) { SelectField selectWidget = SelectField( - selectedIndices: widget.setting.selectedIndices, + getSelectedIndices: () => widget.setting.selectedIndices, title: widget.setting.name, multiSelect: true, - choices: widget.setting.options + actions: widget.setting.actions, + getChoices: () => widget.setting.options .map((option) => SelectChoice( - name: option.name, + name: option.getLocalizedName(context), value: option.value, - description: option.description)) + description: option.getDescription(context))) .toList(), onChanged: (value) { setState(() { diff --git a/lib/settings/widgets/select_setting_card.dart b/lib/settings/widgets/select_setting_card.dart index 69a2648a..8c5d2df6 100644 --- a/lib/settings/widgets/select_setting_card.dart +++ b/lib/settings/widgets/select_setting_card.dart @@ -23,13 +23,14 @@ class _SelectSettingCardState extends State> { @override Widget build(BuildContext context) { SelectField selectWidget = SelectField( - selectedIndices: [widget.setting.selectedIndex], - title: widget.setting.name, - choices: widget.setting.options + getSelectedIndices: () => [widget.setting.selectedIndex], + title: widget.setting.displayName(context), + actions: widget.setting.actions, + getChoices: () => widget.setting.options .map((option) => SelectChoice( - name: option.name, + name: option.getLocalizedName(context), value: option.value, - description: option.description)) + description: option.getDescription(context))) .toList(), onChanged: (value) { setState(() { diff --git a/lib/settings/widgets/setting_action_card.dart b/lib/settings/widgets/setting_action_card.dart index 24f8dd0e..ff4ce716 100644 --- a/lib/settings/widgets/setting_action_card.dart +++ b/lib/settings/widgets/setting_action_card.dart @@ -4,10 +4,10 @@ import 'package:flutter/material.dart'; class SettingActionCard extends StatefulWidget { const SettingActionCard({ - Key? key, + super.key, required this.setting, this.showAsCard = true, - }) : super(key: key); + }); final SettingAction setting; final bool showAsCard; @@ -23,6 +23,8 @@ class _SettingActionCardState extends State { TextTheme textTheme = theme.textTheme; ColorScheme colorScheme = theme.colorScheme; + String description = widget.setting.getDescription(context); + Widget inner = Material( color: Colors.transparent, child: InkWell( @@ -36,13 +38,13 @@ class _SettingActionCardState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - widget.setting.name, + widget.setting.displayName(context), style: textTheme.displaySmall, ), - if (widget.setting.description.isNotEmpty) ...[ + if (description.isNotEmpty) ...[ const SizedBox(height: 4), Text( - widget.setting.description, + description, style: textTheme.bodyMedium, ) ] diff --git a/lib/settings/widgets/setting_group_card.dart b/lib/settings/widgets/setting_group_card.dart index 3077a48c..6f154e08 100644 --- a/lib/settings/widgets/setting_group_card.dart +++ b/lib/settings/widgets/setting_group_card.dart @@ -4,6 +4,7 @@ import 'package:clock_app/settings/screens/settings_group_screen.dart'; import 'package:clock_app/settings/types/setting_group.dart'; import 'package:clock_app/settings/types/setting_item.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class SettingGroupCard extends StatefulWidget { final SettingGroup settingGroup; @@ -77,6 +78,7 @@ class _SettingGroupCardState extends State { ), ); + String description = widget.settingGroup.displayDescription(context); CardContainer cardView = CardContainer( onTap: openSettingGroupScreen, child: Padding( @@ -84,20 +86,21 @@ class _SettingGroupCardState extends State { child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - Icon(widget.settingGroup.icon, color: colorScheme.onBackground), - const SizedBox(width: 16), + if (widget.settingGroup.icon != null) + Icon(widget.settingGroup.icon, color: colorScheme.onBackground), + if (widget.settingGroup.icon != null) const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - widget.settingGroup.name, + widget.settingGroup.displayName(context), style: textTheme.displaySmall, ), - if (widget.settingGroup.description.isNotEmpty) ...[ + if (description.isNotEmpty) ...[ const SizedBox(height: 4), Text( - widget.settingGroup.description, + description, style: textTheme.bodyMedium, ) ] @@ -145,7 +148,7 @@ class SettingGroupHeader extends StatelessWidget { child: Row( children: [ Text( - settingGroup.name, + settingGroup.displayName(context), style: textTheme.headlineMedium?.copyWith( color: colorScheme.primary, ), @@ -157,7 +160,7 @@ class SettingGroupHeader extends StatelessWidget { Padding( padding: const EdgeInsets.only(left: 6.0), child: Text( - "More", + AppLocalizations.of(context)!.settingGroupMore, style: textTheme.titleSmall?.copyWith( color: colorScheme.primary, ), diff --git a/lib/settings/widgets/setting_page_link_card.dart b/lib/settings/widgets/setting_page_link_card.dart index 5c246ddd..d64e9855 100644 --- a/lib/settings/widgets/setting_page_link_card.dart +++ b/lib/settings/widgets/setting_page_link_card.dart @@ -22,6 +22,8 @@ class _SettingPageLinkCardState extends State { ThemeData theme = Theme.of(context); TextTheme textTheme = theme.textTheme; ColorScheme colorScheme = theme.colorScheme; + + String description = widget.setting.getDescription(context); Widget inner = Material( color: Colors.transparent, child: InkWell( @@ -47,13 +49,13 @@ class _SettingPageLinkCardState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - widget.setting.name, + widget.setting.displayName(context), style: textTheme.displaySmall, ), - if (widget.setting.description.isNotEmpty) ...[ + if (description.isNotEmpty) ...[ const SizedBox(height: 4), Text( - widget.setting.description, + description, style: textTheme.bodyMedium, ) ] diff --git a/lib/settings/widgets/settings_top_bar.dart b/lib/settings/widgets/settings_top_bar.dart index 5b9e2ab4..63b4beb3 100644 --- a/lib/settings/widgets/settings_top_bar.dart +++ b/lib/settings/widgets/settings_top_bar.dart @@ -3,16 +3,20 @@ import 'package:clock_app/settings/data/settings_schema.dart'; import 'package:clock_app/settings/types/setting_item.dart'; import 'package:fuzzywuzzy/fuzzywuzzy.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class SettingsTopBar extends StatefulWidget implements PreferredSizeWidget { @override Size get preferredSize => const Size(0, 56); const SettingsTopBar( - {Key? key, required this.onSearch, this.showSearch = false}) - : super(key: key); + {super.key, + required this.onSearch, + this.showSearch = false, + required this.title}); final void Function(List settings) onSearch; + final String title; final bool showSearch; @override @@ -62,7 +66,7 @@ class _SettingsTopBarState extends State { focusedBorder: const OutlineInputBorder(borderSide: BorderSide.none), fillColor: Colors.transparent, - hintText: 'Search for a setting', + hintText: AppLocalizations.of(context)!.searchSettingPlaceholder, hintStyle: Theme.of(context).textTheme.bodyLarge, ), textAlignVertical: TextAlignVertical.center, @@ -82,7 +86,13 @@ class _SettingsTopBarState extends State { ); } else { return AppTopBar( - title: Text("Settings", style: Theme.of(context).textTheme.titleMedium), + title: Text( + widget.title, + style: Theme.of(context).textTheme.titleMedium?.copyWith( + color: + Theme.of(context).colorScheme.onBackground.withOpacity(0.6), + ), + ), actions: [ if (widget.showSearch) IconButton( @@ -94,7 +104,7 @@ class _SettingsTopBarState extends State { icon: Icon( Icons.search, color: - Theme.of(context).colorScheme.onBackground.withOpacity(0.6), + Theme.of(context).colorScheme.onBackground, ), ) ], diff --git a/lib/settings/widgets/slider_setting_card.dart b/lib/settings/widgets/slider_setting_card.dart index cd46df04..e2be84ff 100644 --- a/lib/settings/widgets/slider_setting_card.dart +++ b/lib/settings/widgets/slider_setting_card.dart @@ -9,11 +9,11 @@ class SliderSettingCard extends StatefulWidget { final void Function(double)? onChanged; const SliderSettingCard({ - Key? key, + super.key, required this.setting, this.showAsCard = false, this.onChanged, - }) : super(key: key); + }); @override State createState() => _SliderSettingCardState(); @@ -23,7 +23,7 @@ class _SliderSettingCardState extends State { @override Widget build(BuildContext context) { SliderField sliderCard = SliderField( - title: widget.setting.name, + title: widget.setting.displayName(context), value: widget.setting.value, min: widget.setting.min, max: widget.setting.max, diff --git a/lib/settings/widgets/string_setting_card.dart b/lib/settings/widgets/string_setting_card.dart index 8024e40c..53aa5d1b 100644 --- a/lib/settings/widgets/string_setting_card.dart +++ b/lib/settings/widgets/string_setting_card.dart @@ -2,6 +2,8 @@ import 'package:clock_app/common/widgets/card_container.dart'; import 'package:clock_app/common/widgets/fields/input_field.dart'; import 'package:clock_app/settings/types/setting.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + class StringSettingCard extends StatefulWidget { final StringSetting setting; @@ -9,11 +11,11 @@ class StringSettingCard extends StatefulWidget { final void Function(String)? onChanged; const StringSettingCard({ - Key? key, + super.key, required this.setting, this.showAsCard = false, this.onChanged, - }) : super(key: key); + }); @override State createState() => _StringSettingCardState(); @@ -23,8 +25,8 @@ class _StringSettingCardState extends State { @override Widget build(BuildContext context) { Widget input = InputField( - title: widget.setting.name, - description: widget.setting.description, + title: widget.setting.displayName(context), + description: widget.setting.displayDescription(context), value: widget.setting.value, onChanged: (value) { setState(() { @@ -32,7 +34,7 @@ class _StringSettingCardState extends State { }); widget.onChanged?.call(widget.setting.value); }, - hintText: "Add a label", + hintText: AppLocalizations.of(context)!.labelFieldPlaceholder, ); return widget.showAsCard ? CardContainer(child: input) : input; diff --git a/lib/settings/widgets/switch_setting_card.dart b/lib/settings/widgets/switch_setting_card.dart index e0a341b9..7203a373 100644 --- a/lib/settings/widgets/switch_setting_card.dart +++ b/lib/settings/widgets/switch_setting_card.dart @@ -22,7 +22,7 @@ class _SwitchSettingCardState extends State { @override Widget build(BuildContext context) { SwitchField switchCard = SwitchField( - name: widget.setting.name, + name: widget.setting.displayName(context), value: widget.setting.value, onChanged: (value) { setState(() { diff --git a/lib/settings/widgets/tag_card.dart b/lib/settings/widgets/tag_card.dart index c7a8a9da..7c3de9bf 100644 --- a/lib/settings/widgets/tag_card.dart +++ b/lib/settings/widgets/tag_card.dart @@ -43,7 +43,7 @@ class _TagCardState extends State { ), CardEditMenu(actions: [ getDeletePopupAction(context, widget.onPressDelete), - getDuplicatePopupAction(widget.onPressDuplicate), + getDuplicatePopupAction(context, widget.onPressDuplicate), ]), ], )); diff --git a/lib/settings/widgets/toggle_setting_card.dart b/lib/settings/widgets/toggle_setting_card.dart index 39d8eef6..6bd863b6 100644 --- a/lib/settings/widgets/toggle_setting_card.dart +++ b/lib/settings/widgets/toggle_setting_card.dart @@ -5,11 +5,10 @@ import 'package:flutter/material.dart'; class ToggleSettingCard extends StatefulWidget { const ToggleSettingCard( - {Key? key, + {super.key, required this.setting, this.showAsCard = false, - this.onChanged}) - : super(key: key); + this.onChanged}); final ToggleSetting setting; final bool showAsCard; @@ -23,11 +22,12 @@ class _ToggleSettingCardState extends State> { @override Widget build(BuildContext context) { ToggleField toggleCard = ToggleField( - name: widget.setting.name, - description: widget.setting.description, + name: widget.setting.displayName(context), + description: widget.setting.displayDescription(context), selectedItems: widget.setting.value, options: widget.setting.options - .map((option) => ToggleOption(option.name, option.value)) + .map((option) => + ToggleOption(option.getLocalizedName(context), option.value)) .toList(), onChange: (value) { setState(() { diff --git a/lib/stopwatch/screens/stopwatch_screen.dart b/lib/stopwatch/screens/stopwatch_screen.dart index 6ab7f3c2..a4645316 100644 --- a/lib/stopwatch/screens/stopwatch_screen.dart +++ b/lib/stopwatch/screens/stopwatch_screen.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:awesome_notifications/awesome_notifications.dart'; import 'package:clock_app/common/types/list_controller.dart'; import 'package:clock_app/common/utils/list_storage.dart'; -import 'package:clock_app/common/widgets/linear_progress_bar.dart'; import 'package:clock_app/common/widgets/list/custom_list_view.dart'; import 'package:clock_app/common/widgets/fab.dart'; import 'package:clock_app/notifications/data/notification_channel.dart'; @@ -10,16 +9,14 @@ import 'package:clock_app/notifications/data/update_notification_intervals.dart' import 'package:clock_app/settings/data/settings_schema.dart'; import 'package:clock_app/settings/types/listener_manager.dart'; import 'package:clock_app/settings/types/setting.dart'; -import 'package:clock_app/settings/types/setting_group.dart'; import 'package:clock_app/stopwatch/logic/stopwatch_notification.dart'; import 'package:clock_app/stopwatch/types/lap.dart'; import 'package:clock_app/stopwatch/types/stopwatch.dart'; import 'package:clock_app/stopwatch/widgets/lap_card.dart'; import 'package:clock_app/stopwatch/widgets/stopwatch_ticker.dart'; -import 'package:clock_app/timer/types/time_duration.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/scheduler.dart'; -import 'package:timer_builder/timer_builder.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + class StopwatchScreen extends StatefulWidget { @@ -150,7 +147,7 @@ class _StopwatchScreenState extends State { key: ValueKey(lap), lap: lap, ), - placeholderText: "No laps yet", + placeholderText: AppLocalizations.of(context)!.noLapsMessage, isDeleteEnabled: false, isDuplicateEnabled: false, isReorderable: false, diff --git a/lib/stopwatch/widgets/lap_card.dart b/lib/stopwatch/widgets/lap_card.dart index 5207d70a..5ce040a5 100644 --- a/lib/stopwatch/widgets/lap_card.dart +++ b/lib/stopwatch/widgets/lap_card.dart @@ -1,5 +1,7 @@ import 'package:clock_app/stopwatch/types/lap.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + class LapCard extends StatefulWidget { const LapCard({super.key, required this.lap, this.onInit}); @@ -32,7 +34,7 @@ class _LapCardState extends State { Text(widget.lap.lapTime.toTimeString(showMilliseconds: true), style: Theme.of(context).textTheme.displaySmall), Text( - 'Elapsed Time: ${widget.lap.elapsedTime.toTimeString(showMilliseconds: true)}'), + '${AppLocalizations.of(context)!.elapsedTime}: ${widget.lap.elapsedTime.toTimeString(showMilliseconds: true)}'), ], ), ], diff --git a/lib/stopwatch/widgets/stopwatch_ticker.dart b/lib/stopwatch/widgets/stopwatch_ticker.dart index b542e065..5a3bae65 100644 --- a/lib/stopwatch/widgets/stopwatch_ticker.dart +++ b/lib/stopwatch/widgets/stopwatch_ticker.dart @@ -6,6 +6,8 @@ import 'package:clock_app/stopwatch/widgets/lap_comparer.dart'; import 'package:clock_app/timer/types/time_duration.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + class StopwatchTicker extends StatefulWidget { const StopwatchTicker({super.key, required this.stopwatch}); @@ -106,7 +108,7 @@ class _StopwatchTickerState extends State { LapComparer( stopwatch: widget.stopwatch, comparisonLap: widget.stopwatch.previousLap, - label: "Previous", + label: AppLocalizations.of(context)!.stopwatchPrevious, color: Colors.blue, ), ], @@ -115,7 +117,7 @@ class _StopwatchTickerState extends State { LapComparer( stopwatch: widget.stopwatch, comparisonLap: widget.stopwatch.fastestLap, - label: "Fastest", + label: AppLocalizations.of(context)!.stopwatchFastest, color: Colors.red, ), ], @@ -124,7 +126,7 @@ class _StopwatchTickerState extends State { LapComparer( stopwatch: widget.stopwatch, comparisonLap: widget.stopwatch.slowestLap, - label: "Slowest", + label: AppLocalizations.of(context)!.stopwatchSlowest, color: Colors.orange, ), ], @@ -133,7 +135,7 @@ class _StopwatchTickerState extends State { LapComparer( stopwatch: widget.stopwatch, comparisonLap: widget.stopwatch.averageLap, - label: "Average", + label: AppLocalizations.of(context)!.stopwatchAverage, color: Colors.green, showLapNumber: false, ), diff --git a/lib/system/logic/handle_intents.dart b/lib/system/logic/handle_intents.dart index d6b9219b..421115e3 100644 --- a/lib/system/logic/handle_intents.dart +++ b/lib/system/logic/handle_intents.dart @@ -4,6 +4,8 @@ import 'package:clock_app/alarm/types/alarm.dart'; import 'package:clock_app/alarm/types/schedules/weekly_alarm_schedule.dart'; import 'package:clock_app/common/types/notification_type.dart'; import 'package:clock_app/common/utils/list_storage.dart'; +import 'package:clock_app/navigation/types/app_visibility.dart'; +import 'package:clock_app/notifications/types/fullscreen_notification_manager.dart'; import 'package:clock_app/settings/types/listener_manager.dart'; import 'package:flutter/material.dart' hide Intent; import 'package:receive_intent/receive_intent.dart'; @@ -92,6 +94,10 @@ void handleIntent(Intent? receivedIntent, BuildContext context, Function(Alarm) break; case "android.intent.action.VIEW_TIMERS": break; + case "SELECT_NOTIFICATION": + AlarmNotificationManager.appVisibilityWhenCreated = AppVisibility.state; + // print("************************************** ${AppVisibility.state}"); + break; default: break; } diff --git a/lib/theme/data/color_scheme_settings_schema.dart b/lib/theme/data/color_scheme_settings_schema.dart index 4c443afc..03c3e98f 100644 --- a/lib/theme/data/color_scheme_settings_schema.dart +++ b/lib/theme/data/color_scheme_settings_schema.dart @@ -2,41 +2,108 @@ import 'package:clock_app/settings/types/setting.dart'; import 'package:clock_app/settings/types/setting_enable_condition.dart'; import 'package:clock_app/settings/types/setting_group.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; const colorSchemeSettingsSchemaVersion = 1; SettingGroup colorSchemeSettingsSchema = SettingGroup( version: colorSchemeSettingsSchemaVersion, "Color Scheme", + (context) => AppLocalizations.of(context)!.colorsSettingGroup, [ - StringSetting("Name", "Color Scheme"), - SettingGroup("Background", [ - ColorSetting("Color", Colors.white), - ColorSetting("Text", Colors.black), - ]), - SettingGroup("Card", [ - ColorSetting("Color", Colors.white), - ColorSetting("Text", Colors.black), - ]), - SettingGroup("Accent", [ - ColorSetting("Color", Colors.cyan), - ColorSetting("Text", Colors.white), - ]), - SettingGroup("Shadow", [ - SwitchSetting("Use Accent as Shadow", false), - ColorSetting("Color", Colors.black, enableConditions: [ - ValueCondition(["Use Accent as Shadow"], (value)=>value==false), - ]), - ]), - SettingGroup("Outline", [ - SwitchSetting("Use Accent as Outline", false), - ColorSetting("Color", Colors.black, enableConditions: [ - ValueCondition(["Use Accent as Outline"], (value)=>value==false), - ]), - ]), - SettingGroup("Error", [ - ColorSetting("Color", Colors.red), - ColorSetting("Text", Colors.white), - ]), + StringSetting("Name", (context) => AppLocalizations.of(context)!.nameField, + "Color Scheme"), + SettingGroup( + "Background", + (context) => + AppLocalizations.of(context)!.colorSchemeBackgroundSettingGroup, + [ + ColorSetting( + "Color", + (context) => AppLocalizations.of(context)!.colorSetting, + Colors.white), + ColorSetting( + "Text", + (context) => AppLocalizations.of(context)!.textColorSetting, + Colors.black), + ]), + SettingGroup( + "Card", + (context) => AppLocalizations.of(context)!.colorSchemeCardSettingGroup, + [ + ColorSetting( + "Color", + (context) => AppLocalizations.of(context)!.colorSetting, + Colors.white), + ColorSetting( + "Text", + (context) => AppLocalizations.of(context)!.textColorSetting, + Colors.black), + ]), + SettingGroup( + "Accent", + (context) => + AppLocalizations.of(context)!.colorSchemeAccentSettingGroup, + [ + ColorSetting( + "Color", + (context) => AppLocalizations.of(context)!.colorSetting, + Colors.cyan), + ColorSetting( + "Text", + (context) => AppLocalizations.of(context)!.textColorSetting, + Colors.white), + ]), + SettingGroup( + "Shadow", + (context) => + AppLocalizations.of(context)!.colorSchemeShadowSettingGroup, + [ + SwitchSetting( + "Use Accent as Shadow", + (context) => AppLocalizations.of(context)! + .colorSchemeUseAccentAsShadowSetting, + false), + ColorSetting( + "Color", + (context) => AppLocalizations.of(context)!.colorSetting, + Colors.black, + enableConditions: [ + ValueCondition( + ["Use Accent as Shadow"], (value) => value == false), + ]), + ]), + SettingGroup( + "Outline", + (context) => + AppLocalizations.of(context)!.colorSchemeOutlineSettingGroup, + [ + SwitchSetting( + "Use Accent as Outline", + (context) => AppLocalizations.of(context)! + .colorSchemeUseAccentAsOutlineSetting, + false), + ColorSetting( + "Color", + (context) => AppLocalizations.of(context)!.colorSetting, + Colors.black, + enableConditions: [ + ValueCondition( + ["Use Accent as Outline"], (value) => value == false), + ]), + ]), + SettingGroup( + "Error", + (context) => AppLocalizations.of(context)!.colorSchemeErrorSettingGroup, + [ + ColorSetting( + "Color", + (context) => AppLocalizations.of(context)!.colorSetting, + Colors.red), + ColorSetting( + "Text", + (context) => AppLocalizations.of(context)!.textColorSetting, + Colors.white), + ]), ], ); diff --git a/lib/theme/data/style_theme_settings_schema.dart b/lib/theme/data/style_theme_settings_schema.dart index f55ef1da..9f45e118 100644 --- a/lib/theme/data/style_theme_settings_schema.dart +++ b/lib/theme/data/style_theme_settings_schema.dart @@ -1,24 +1,72 @@ import 'package:clock_app/settings/types/setting.dart'; import 'package:clock_app/settings/types/setting_group.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; const styleThemeSettingsSchemaVersion = 1; SettingGroup styleThemeSettingsSchema = SettingGroup( version: styleThemeSettingsSchemaVersion, "App Style", + (context) => AppLocalizations.of(context)!.styleSettingGroup, [ - StringSetting("Name", "Style Theme"), - SettingGroup("Shape", [ - SliderSetting("Corner Roundness", 0, 36, 16), - ]), - SettingGroup("Shadow", [ - SliderSetting("Elevation", 0, 10, 1), - SliderSetting("Opacity", 0, 100, 20), - SliderSetting("Blur", 0, 16, 1), - SliderSetting("Spread", 0, 8, 0), - ]), - SettingGroup("Outline", [ - SliderSetting("Width", 0, 8, 0), - ]), + StringSetting("Name", (context) => AppLocalizations.of(context)!.nameField, + "Style Theme"), + SettingGroup( + "Shape", + (context) => AppLocalizations.of(context)!.styleThemeShapeSettingGroup, + [ + SliderSetting( + "Corner Roundness", + (context) => + AppLocalizations.of(context)!.styleThemeRadiusSetting, + 0, + 36, + 16), + ]), + SettingGroup( + "Shadow", + (context) => AppLocalizations.of(context)!.styleThemeShadowSettingGroup, + [ + SliderSetting( + "Elevation", + (context) => + AppLocalizations.of(context)!.styleThemeElevationSetting, + 0, + 10, + 1), + SliderSetting( + "Opacity", + (context) => + AppLocalizations.of(context)!.styleThemeOpacitySetting, + 0, + 100, + 20), + SliderSetting( + "Blur", + (context) => AppLocalizations.of(context)!.styleThemeBlurSetting, + 0, + 16, + 1), + SliderSetting( + "Spread", + (context) => + AppLocalizations.of(context)!.styleThemeSpreadSetting, + 0, + 8, + 0), + ]), + SettingGroup( + "Outline", + (context) => + AppLocalizations.of(context)!.styleThemeOutlineSettingGroup, + [ + SliderSetting( + "Width", + (context) => + AppLocalizations.of(context)!.styleThemeOutlineWidthSetting, + 0, + 8, + 0), + ]), ], ); diff --git a/lib/theme/widgets/theme_card.dart b/lib/theme/widgets/theme_card.dart index bfa0aebb..ca5bc643 100644 --- a/lib/theme/widgets/theme_card.dart +++ b/lib/theme/widgets/theme_card.dart @@ -74,7 +74,7 @@ class ThemeCard extends StatelessWidget { CardEditMenu(actions: [ if (themeItem.isDeletable) getDeletePopupAction(context, onPressDelete), - getDuplicatePopupAction(onPressDuplicate), + getDuplicatePopupAction(context,onPressDuplicate), ]), ], ), diff --git a/lib/theme/widgets/theme_preview_card.dart b/lib/theme/widgets/theme_preview_card.dart index 8ca5f6c0..72cae966 100644 --- a/lib/theme/widgets/theme_preview_card.dart +++ b/lib/theme/widgets/theme_preview_card.dart @@ -1,6 +1,7 @@ import 'package:clock_app/common/logic/card_decoration.dart'; import 'package:clock_app/common/widgets/card_container.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class ThemePreviewCard extends StatelessWidget { const ThemePreviewCard({ @@ -19,60 +20,60 @@ class ThemePreviewCard extends StatelessWidget { color: colorScheme.background, child: Padding( padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Text( - "Preview", - style: textTheme.headlineMedium?.copyWith( - color: colorScheme.onBackground, + child: SizedBox( + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Text( + AppLocalizations.of(context)!.previewLabel, + style: textTheme.headlineMedium?.copyWith( + color: colorScheme.onBackground, + ), ), ), - ), - const SizedBox(height: 8.0), - Row( - children: [ - Expanded( - flex: 1, - child: CardContainer( + const SizedBox(height: 8.0), + Wrap( + children: [ + CardContainer( color: getCardColor(context), key: const Key("Preview Card - Card"), child: Padding( padding: const EdgeInsets.all(16.0), child: Text( - "Card", + AppLocalizations.of(context)!.cardLabel, style: textTheme.headlineSmall?.copyWith( color: colorScheme.onSurface, ), ), ), ), - ), - CardContainer( - key: const Key("Preview Card - Accent"), - color: colorScheme.primary, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Text("Accent", - style: textTheme.bodyMedium - ?.copyWith(color: colorScheme.onPrimary)), - ), - ), - CardContainer( - key: const Key("Preview Card - Error"), - color: colorScheme.error, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Text("Error", - style: textTheme.bodyMedium - ?.copyWith(color: colorScheme.onError)), + CardContainer( + key: const Key("Preview Card - Accent"), + color: colorScheme.primary, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Text(AppLocalizations.of(context)!.accentLabel, + style: textTheme.bodyMedium + ?.copyWith(color: colorScheme.onPrimary)), + ), ), - ) - ], - ), - ], + CardContainer( + key: const Key("Preview Card - Error"), + color: colorScheme.error, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Text(AppLocalizations.of(context)!.errorLabel, + style: textTheme.bodyMedium + ?.copyWith(color: colorScheme.onError)), + ), + ) + ], + ), + ], + ), ), ), ); diff --git a/lib/timer/data/timer_list_filters.dart b/lib/timer/data/timer_list_filters.dart index 391b2669..e53548f7 100644 --- a/lib/timer/data/timer_list_filters.dart +++ b/lib/timer/data/timer_list_filters.dart @@ -2,28 +2,31 @@ import 'package:clock_app/common/types/list_filter.dart'; import 'package:clock_app/common/types/tag.dart'; import 'package:clock_app/common/utils/list_storage.dart'; import 'package:clock_app/timer/types/timer.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; final List> timerListFilters = [ - ListFilterSelect("State", [ + ListFilterSelect( + (context) => AppLocalizations.of(context)!.stateFilterGroup, [ ListFilter( - 'Running', + (context) => AppLocalizations.of(context)!.runningTimerFilter, (timer) => timer.isRunning, ), ListFilter( - 'Paused', + (context) => AppLocalizations.of(context)!.pausedTimerFilter, (timer) => timer.isPaused, ), ListFilter( - 'Stopped', + (context) => AppLocalizations.of(context)!.stoppedTimerFilter, (timer) => timer.isStopped, ), ]), // - DynamicListFilterMultiSelect("Tags", () { + DynamicListFilterMultiSelect( + (context) => AppLocalizations.of(context)!.tagsSetting, () { final tags = loadListSync("tags"); return tags.map((tag) { return ListFilter( - tag.name, + (context) => tag.name, (timer) => timer.tags.any((element) => element.id == tag.id), id: tag.id, ); diff --git a/lib/timer/data/timer_settings_schema.dart b/lib/timer/data/timer_settings_schema.dart index 4d6ca647..2b189dfd 100644 --- a/lib/timer/data/timer_settings_schema.dart +++ b/lib/timer/data/timer_settings_schema.dart @@ -3,12 +3,15 @@ import 'package:clock_app/audio/audio_channels.dart'; import 'package:clock_app/audio/types/ringtone_player.dart'; import 'package:clock_app/common/logic/tags.dart'; import 'package:clock_app/common/types/file_item.dart'; +import 'package:clock_app/common/types/popup_action.dart'; import 'package:clock_app/common/types/tag.dart'; import 'package:clock_app/common/utils/ringtones.dart'; +import 'package:clock_app/settings/screens/ringtones_screen.dart'; +import 'package:clock_app/settings/screens/tags_screen.dart'; import 'package:clock_app/settings/types/setting.dart'; import 'package:clock_app/settings/types/setting_enable_condition.dart'; import 'package:clock_app/settings/types/setting_group.dart'; - +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:clock_app/timer/types/time_duration.dart'; import 'package:flutter/material.dart'; @@ -17,38 +20,71 @@ const timerSettingSchemeVersion = 1; SettingGroup timerSettingsSchema = SettingGroup( version: timerSettingSchemeVersion, "Timer Setting", + (context) => "Timer Setting", [ - StringSetting("Label", ""), + StringSetting( + "Label", (context) => AppLocalizations.of(context)!.labelField, ""), SettingGroup( "Sound and Vibration", + (context) => AppLocalizations.of(context)!.soundAndVibrationSettingGroup, [ SettingGroup( "Sound", + (context) => AppLocalizations.of(context)!.soundSettingGroup, [ DynamicSelectSetting( "Melody", + (context) => AppLocalizations.of(context)!.melodySetting, getRingtoneOptions, onChange: (context, index) { RingtonePlayer.stop(); }, + actions: [ + MenuAction( + "Add", + (context) async { + await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => const RingtonesScreen()), + ); + }, + Icons.add, + ), + ], + // shouldCloseOnSelect: false, ), SelectSetting( - "Audio Channel", audioChannelOptions, - onChange: (context, index) { + "Audio Channel", + (context) => AppLocalizations.of(context)!.audioChannelSetting, + audioChannelOptions, onChange: (context, index) { RingtonePlayer.stop(); }), - SliderSetting("Volume", 0, 100, 100, unit: "%"), - SwitchSetting("Rising Volume", false, - description: "Gradually increase volume over time"), + SliderSetting( + "Volume", + (context) => AppLocalizations.of(context)!.volumeSetting, + 0, + 100, + 100, + unit: "%"), + SwitchSetting( + "Rising Volume", + (context) => AppLocalizations.of(context)!.risingVolumeSetting, + false, + // description: "Gradually increase volume over time", + ), DurationSetting( - "Time To Full Volume", const TimeDuration(minutes: 1), + "Time To Full Volume", + (context) => + AppLocalizations.of(context)!.timeToFullVolumeSetting, + const TimeDuration(minutes: 1), enableConditions: [ ValueCondition(["Rising Volume"], (value) => value == true) ]), ], ), - SwitchSetting("Vibration", false), + SwitchSetting("Vibration", + (context) => AppLocalizations.of(context)!.vibrationSetting, false), ], icon: Icons.volume_up, summarySettings: [ @@ -56,11 +92,25 @@ SettingGroup timerSettingsSchema = SettingGroup( "Vibration", ], ), - SliderSetting("Add Length", 1, 30, 1, unit: "minutes", snapLength: 1), + SliderSetting("Add Length", + (context) => AppLocalizations.of(context)!.addLengthSetting, 1, 30, 1, + unit: "minutes", snapLength: 1), DynamicMultiSelectSetting( "Tags", + (context) => AppLocalizations.of(context)!.tagsSetting, getTagOptions, defaultValue: [], + actions: [ + MenuAction( + "Add", + (context) async { + await Navigator.of(context).push( + MaterialPageRoute(builder: (context) => const TagsScreen()), + ); + }, + Icons.add, + ), + ], ), ], ); diff --git a/lib/timer/data/timer_sort_options.dart b/lib/timer/data/timer_sort_options.dart index 5bdb89a6..d5c8caa8 100644 --- a/lib/timer/data/timer_sort_options.dart +++ b/lib/timer/data/timer_sort_options.dart @@ -1,13 +1,14 @@ import 'package:clock_app/common/types/list_filter.dart'; import 'package:clock_app/timer/types/timer.dart'; - -const List> timerSortOptions = [ - ListSortOption("Remaining Time Descending", "9-1", sortRemainingTimeDescending), - ListSortOption("Remaining Time Ascending", "1-9", sortRemainingTimeAscending), - ListSortOption("Duration Descending", "5:00-1:00", sortTotalDurationDescending), - ListSortOption("Duration Ascending", "1:00-5:00", sortTotalDurationAscending), - ListSortOption("Name Ascending", "A-Z", sortNameAscending), - ListSortOption("Name Descending", "Z-A", sortNameDescending), +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +final List> timerSortOptions = [ + ListSortOption((context) => AppLocalizations.of(context)!.remainingTimeDesc, sortRemainingTimeDescending), + ListSortOption((context) => AppLocalizations.of(context)!.remainingTimeAsc, sortRemainingTimeAscending), + ListSortOption((context) => AppLocalizations.of(context)!.durationAsc, sortTotalDurationAscending), + ListSortOption((context) => AppLocalizations.of(context)!.durationDesc, sortTotalDurationDescending), + ListSortOption((context) => AppLocalizations.of(context)!.nameAsc, sortNameAscending), + ListSortOption((context) => AppLocalizations.of(context)!.nameDesc, sortNameDescending), ]; diff --git a/lib/timer/logic/edit_duration_picker_mode.dart b/lib/timer/logic/edit_duration_picker_mode.dart index c81c14f8..d078582c 100644 --- a/lib/timer/logic/edit_duration_picker_mode.dart +++ b/lib/timer/logic/edit_duration_picker_mode.dart @@ -5,7 +5,8 @@ import 'package:clock_app/settings/data/settings_schema.dart'; import 'package:clock_app/settings/types/setting.dart'; import 'package:flutter/material.dart'; -Future editDurationPickerMode(BuildContext context, VoidCallback onChange) async { +Future editDurationPickerMode( + BuildContext context, VoidCallback onChange) async { SelectSetting setting = appSettings .getGroup("General") .getGroup("Display") @@ -19,14 +20,14 @@ Future editDurationPickerMode(BuildContext context, VoidCallback onChange) // setState(() {}); }, title: setting.name, - description: setting.description, - choices: setting.options + description: setting.getDescription(context), + getChoices: () => setting.options .map((option) => SelectChoice( - name: option.name, + name: option.getLocalizedName(context), value: option.value, - description: option.description)) + description: option.getDescription(context))) .toList(), - initialSelectedIndices: [setting.selectedIndex], + getCurrentSelectedIndices: () => [setting.selectedIndex], multiSelect: false, ); diff --git a/lib/timer/screens/presets_screen.dart b/lib/timer/screens/presets_screen.dart index 5d63941d..f0d75f9e 100644 --- a/lib/timer/screens/presets_screen.dart +++ b/lib/timer/screens/presets_screen.dart @@ -48,7 +48,7 @@ class _PresetsScreenState extends State { _listController.changeItems((presets) {}); }, // onDeleteItem: _handleDeleteTimer, - placeholderText: "No timers created", + placeholderText: "No presets created", reloadOnPop: true, ), ), diff --git a/lib/timer/screens/timer_fullscreen.dart b/lib/timer/screens/timer_fullscreen.dart index 4e088667..ea6a0a5d 100644 --- a/lib/timer/screens/timer_fullscreen.dart +++ b/lib/timer/screens/timer_fullscreen.dart @@ -9,6 +9,7 @@ import 'package:clock_app/timer/types/timer.dart'; import 'package:clock_app/timer/utils/timer_id.dart'; import 'package:clock_app/timer/widgets/timer_progress_bar.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class TimerFullscreen extends StatefulWidget { const TimerFullscreen({ @@ -80,7 +81,7 @@ class _TimerFullscreenState extends State { }); } }, - child: const Text("Edit")) + child: Text(AppLocalizations.of(context)!.editButton)) ]), body: OrientationBuilder(builder: (context, orientation) { double buttonSize = orientation == Orientation.portrait ? 32 : 32; @@ -88,8 +89,6 @@ class _TimerFullscreenState extends State { double width = MediaQuery.of(context).size.width - 64; double height = MediaQuery.of(context).size.height - 136; - print('$width $height'); - return SizedBox( width: orientation == Orientation.portrait ? double.infinity : null, height: orientation == Orientation.landscape ? double.infinity : null, diff --git a/lib/timer/screens/timer_screen.dart b/lib/timer/screens/timer_screen.dart index baeb8884..71f7e56e 100644 --- a/lib/timer/screens/timer_screen.dart +++ b/lib/timer/screens/timer_screen.dart @@ -22,6 +22,7 @@ import 'package:clock_app/common/widgets/fab.dart'; import 'package:clock_app/common/widgets/list/persistent_list_view.dart'; import 'package:clock_app/timer/types/timer.dart'; import 'package:clock_app/timer/widgets/timer_card.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; typedef TimerCardBuilder = Widget Function( BuildContext context, @@ -242,7 +243,7 @@ class _TimerScreenState extends State { // _listController.changeItems((item) {}); }, onDeleteItem: _onDeleteTimer, - placeholderText: "No timers created", + placeholderText: AppLocalizations.of(context)!.noTimerMessage, reloadOnPop: true, listFilters: _showFilters.value ? timerListFilters : [], sortOptions: _showSort.value ? timerSortOptions : [], diff --git a/lib/timer/types/timer.dart b/lib/timer/types/timer.dart index 22669b1b..1578490c 100644 --- a/lib/timer/types/timer.dart +++ b/lib/timer/types/timer.dart @@ -24,6 +24,7 @@ class ClockTimer extends CustomizableListItem { late int _id; SettingGroup _settings = SettingGroup( "Timer Settings", + (context) => "Timer Settings", appSettings .getGroup("Timer") .getGroup("Default Settings") @@ -225,6 +226,7 @@ class ClockTimer extends CustomizableListItem { _id = json['id'] ?? UniqueKey().hashCode; _settings = SettingGroup( "Timer Settings", + (context) => "Timer Settings", appSettings .getGroup("Timer") .getGroup("Default Settings") diff --git a/lib/timer/widgets/duration_picker.dart b/lib/timer/widgets/duration_picker.dart index a6157313..ddc71e1c 100644 --- a/lib/timer/widgets/duration_picker.dart +++ b/lib/timer/widgets/duration_picker.dart @@ -3,6 +3,8 @@ import 'package:clock_app/timer/logic/edit_duration_picker_mode.dart'; import 'package:clock_app/timer/logic/get_duration_picker.dart'; import 'package:clock_app/timer/types/time_duration.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + Future showDurationPicker( BuildContext context, { @@ -32,7 +34,7 @@ Future showDurationPicker( children: [ // const SizedBox(width: 8), Text( - "Choose Duration", + AppLocalizations.of(context)!.durationPickerTitle, style: TimePickerTheme.of(context).helpTextStyle ?? Theme.of(context).textTheme.labelSmall, ), @@ -41,7 +43,7 @@ Future showDurationPicker( onPressed: () => editDurationPickerMode( context, () => setState(() {})), child: Text( - "Mode", + AppLocalizations.of(context)!.timePickerModeButton, style: Theme.of(context) .textTheme .titleSmall diff --git a/lib/timer/widgets/timer_card.dart b/lib/timer/widgets/timer_card.dart index 1fc64f7e..3008ec00 100644 --- a/lib/timer/widgets/timer_card.dart +++ b/lib/timer/widgets/timer_card.dart @@ -15,7 +15,8 @@ class TimerCard extends StatefulWidget { required this.onToggleState, required this.onPressDelete, required this.onPressDuplicate, - required this.onPressReset, required this.onPressAddTime, + required this.onPressReset, + required this.onPressAddTime, }); final ClockTimer timer; @@ -138,17 +139,17 @@ class _TimerCardState extends State { const Spacer(), CardEditMenu(actions: [ getDeletePopupAction(context, widget.onPressDelete), - getDuplicatePopupAction(widget.onPressDuplicate), + getDuplicatePopupAction(context, widget.onPressDuplicate), if (!widget.timer.isStopped) - PopupAction( + MenuAction( "Reset", - widget.onPressReset, + (context) => widget.onPressReset(), Icons.replay_rounded, ), if (!widget.timer.isStopped) - PopupAction( + MenuAction( '+${widget.timer.addLength.floor()}:00', - widget.onPressAddTime, + (context) => widget.onPressAddTime(), Icons.add_rounded, ) ]), diff --git a/lib/timer/widgets/timer_picker.dart b/lib/timer/widgets/timer_picker.dart index c5bc0718..32f54f37 100644 --- a/lib/timer/widgets/timer_picker.dart +++ b/lib/timer/widgets/timer_picker.dart @@ -9,6 +9,8 @@ import 'package:clock_app/timer/types/time_duration.dart'; import 'package:clock_app/timer/types/timer.dart'; import 'package:clock_app/timer/types/timer_preset.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + Future?> showTimerPicker( BuildContext context, { @@ -37,7 +39,7 @@ Future?> showTimerPicker( isSaveEnabled: timer.duration.inSeconds > 0, // title: "Choose Duration", additionalAction: ModalAction( - title: "Customize", + title: AppLocalizations.of(context)!.customizeButton, onPressed: () async { Navigator.of(context).pop(PickerResult(timer, true)); }, @@ -52,7 +54,9 @@ Future?> showTimerPicker( Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text("Presets", style: textTheme.labelMedium), + Text(AppLocalizations.of(context)!.presetsSetting, + + style: textTheme.labelMedium), const Spacer(), TextButton( style: TextButton.styleFrom( @@ -79,7 +83,7 @@ Future?> showTimerPicker( }); }, child: Text( - "Edit", + AppLocalizations.of(context)!.editButton, style: textTheme.labelSmall ?.copyWith(color: colorScheme.primary), ), @@ -128,7 +132,7 @@ Future?> showTimerPicker( Widget title() => Row( children: [ Text( - "Choose Duration", + AppLocalizations.of(context)!.durationPickerTitle, style: TimePickerTheme.of(context).helpTextStyle ?? Theme.of(context).textTheme.labelSmall, ), @@ -137,7 +141,7 @@ Future?> showTimerPicker( onPressed: () => editDurationPickerMode( context, () => setState(() {})), child: Text( - "Mode", + AppLocalizations.of(context)!.timePickerModeButton, style: Theme.of(context) .textTheme .titleSmall diff --git a/lib/timer/widgets/timer_preset_card.dart b/lib/timer/widgets/timer_preset_card.dart index 92007e1c..192b618c 100644 --- a/lib/timer/widgets/timer_preset_card.dart +++ b/lib/timer/widgets/timer_preset_card.dart @@ -50,7 +50,7 @@ class _TimerPresetCardState extends State { ), CardEditMenu(actions: [ getDeletePopupAction(context, widget.onPressDelete), - getDuplicatePopupAction(widget.onPressDuplicate), + getDuplicatePopupAction(context, widget.onPressDuplicate), ]), ], )); diff --git a/lib/widgets/logic/update_widgets.dart b/lib/widgets/logic/update_widgets.dart new file mode 100644 index 00000000..d69c14d3 --- /dev/null +++ b/lib/widgets/logic/update_widgets.dart @@ -0,0 +1,45 @@ +import 'package:clock_app/common/utils/time_format.dart'; +import 'package:clock_app/settings/data/general_settings_schema.dart'; +import 'package:clock_app/settings/data/settings_schema.dart'; +import 'package:flutter/material.dart'; +import 'package:home_widget/home_widget.dart'; + +void setDigitalClockWidgetData(BuildContext context) async { + final digitalClockSettingGroup = + appSettings.getGroup('Widgets').getGroup('Digital Clock'); + final bool showDate = + digitalClockSettingGroup.getGroup('Layout').getSetting('Show Date').value; + final int timeSize = digitalClockSettingGroup + .getGroup('Layout') + .getSetting('Time Size') + .value + .round(); + final int dateSize = digitalClockSettingGroup + .getGroup('Layout') + .getSetting('Date Size') + .value + .round(); + final String textColor = + '#${digitalClockSettingGroup.getGroup('Text').getSetting('Color').value.value.toRadixString(16)}'; + final String timeFormat = getTimeFormatString(context, appSettings + .getGroup('General') + .getGroup('Display') + .getSetting('Time Format') + .value); + + await HomeWidget.saveWidgetData("timeFormat", timeFormat); + await HomeWidget.saveWidgetData('showDate', showDate); + await HomeWidget.saveWidgetData('timeSize', timeSize); + await HomeWidget.saveWidgetData('dateSize', dateSize); + await HomeWidget.saveWidgetData('textColor', textColor); + + updateDigitalClockWidget(); +} + +void updateDigitalClockWidget() { + HomeWidget.updateWidget( + androidName: 'DigitalClockWidgetProvider', + name: 'DigitalClockWidgetProvider', + qualifiedAndroidName: 'com.vicolo.chrono.DigitalClockWidgetProvider', + ); +} diff --git a/pubspec.lock b/pubspec.lock index 6d07789f..457ce5dd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -384,6 +384,11 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" flutter_oss_licenses: dependency: "direct main" description: @@ -467,6 +472,15 @@ packages: url: "https://github.com/AhsanSarwar45/great_list_view" source: git version: "0.2.3" + home_widget: + dependency: "direct main" + description: + path: "." + ref: main + resolved-ref: "5788ac45f62bef72ff44c52cbd77dc1f9258f633" + url: "https://github.com/AhsanSarwar45/home_widget" + source: git + version: "0.5.0" html: dependency: transitive description: @@ -587,6 +601,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.2" + locale_names: + dependency: "direct main" + description: + name: locale_names + sha256: "7a89ca54072f4f13d0f5df5a9ba69337554bf2fd057d1dd2a238898f3f159374" + url: "https://pub.dev" + source: hosted + version: "1.1.1" logging: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index a8c69df6..af25ae43 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,9 +12,11 @@ dependencies: sdk: flutter flutter_boot_receiver: ^1.1.0 + flutter_localizations: + sdk: flutter + intl: any # flutter_boot_receiver: # path: "../flutter_boot_receiver" - intl: ^0.19.0 timezone: ^0.9.1 timer_builder: ^2.0.0 path_provider: ^2.0.11 @@ -65,8 +67,14 @@ dependencies: watcher: ^1.1.0 dynamic_color: ^1.7.0 material_color_utilities: ^0.8.0 - flutter_oss_licenses: ^3.0.2 - + flutter_oss_licenses: ^3.0.2 + locale_names: ^1.1.1 + # home_widget: ^0.5.0 + home_widget: + git: + url: https://github.com/AhsanSarwar45/home_widget + ref: main + dev_dependencies: flutter_test: @@ -76,17 +84,20 @@ dev_dependencies: change_app_package_name: ^1.1.0 dependency_validator: ^3.2.3 +dependency_overrides: + intl: any + flutter: + generate: true uses-material-design: true assets: - assets/timezones.db - assets/images/ + - assets/contributors/ + - assets/contributors/avatars/ + - assets/patreons/ - assets/ringtones/ - - assets/contributors.json fonts: - - family: Montserrat - fonts: - - asset: fonts/Montserrat/Montserrat-VariableFont.ttf - family: Rubik fonts: - asset: fonts/Rubik/Rubik-VariableFont.ttf diff --git a/scripts/contributors.py b/scripts/contributors.py new file mode 100644 index 00000000..489d2d1f --- /dev/null +++ b/scripts/contributors.py @@ -0,0 +1,44 @@ +import requests +import os +import json + +def fetch_contributors(repo_owner, repo_name): + url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/contributors" + response = requests.get(url) + contributors_data = response.json() + return contributors_data + +def download_avatar(contributor, output_dir): + avatar_url = contributor['avatar_url'] + avatar_name = f"{avatar_url.split('/')[-1]}.jpg" + avatar_path = os.path.join(output_dir, avatar_name) + with open(avatar_path, 'wb') as avatar_file: + response = requests.get(avatar_url) + avatar_file.write(response.content) + return avatar_name + +def main(repo_owner, repo_name): + contributors_data = fetch_contributors(repo_owner, repo_name) + output_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../assets/contributors/') + avatar_output_dir = os.path.join(output_dir, 'avatars') + json_output_dir = os.path.join(output_dir, 'git.json') + os.makedirs(avatar_output_dir, exist_ok=True) + + contributors = [] + for contributor in contributors_data: + avatar_name = download_avatar(contributor, avatar_output_dir) + contributor_info = { + 'username': contributor['login'], + 'avatar_url': f'assets/contributors/avatars/{avatar_name}', + 'profile_url': contributor['html_url'] + } + contributors.append(contributor_info) + + with open(json_output_dir, 'w') as json_file: + json.dump(contributors, json_file, indent=4) + print("Contributors data saved to git.json") + +if __name__ == "__main__": + repo_owner = "vicolo-dev" + repo_name = "chrono" + main(repo_owner, repo_name) diff --git a/scripts/patreons.py b/scripts/patreons.py new file mode 100644 index 00000000..802fd687 --- /dev/null +++ b/scripts/patreons.py @@ -0,0 +1,26 @@ +import csv +import json +import requests +import os + +def csv_to_json(csv_file, json_file): + members = [] + with open(csv_file, 'r') as file: + csv_reader = csv.DictReader(file) + for row in csv_reader: + if(float(row['Lifetime Amount']) > 0): + member_info = { + 'name': row['Name'], + 'lifetime_amount': row['Lifetime Amount'], + 'email': row['Email'], + } + members.append(member_info) + json_output_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../assets/patreons/') + os.makedirs(json_output_dir, exist_ok=True) + json_output_path = os.path.join(json_output_dir, 'patreons.json') + with open(json_output_path, 'w') as json_file: + json.dump(members, json_file, indent=4) + print("CSV converted to JSON") + +if __name__ == "__main__": + csv_to_json('patreons.csv', 'patreons.json') diff --git a/test/alarm/logic/schedule_description_test.dart b/test/alarm/logic/schedule_description_test.dart index 5b44a6bf..5c717db5 100644 --- a/test/alarm/logic/schedule_description_test.dart +++ b/test/alarm/logic/schedule_description_test.dart @@ -6,15 +6,20 @@ import 'package:clock_app/common/types/time.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:intl/intl.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; void testDescription(String name, Function(BuildContext) callback) { testWidgets(name, (WidgetTester tester) async { await tester.pumpWidget( - Builder( - builder: (BuildContext context) { - callback(context); - return const Placeholder(); - }, + Localizations( + delegates: AppLocalizations.localizationsDelegates, + locale: const Locale('en'), + child: Builder( + builder: (BuildContext context) { + callback(context); + return const Placeholder(); + }, + ), ), ); }); diff --git a/test/alarm/widgets/alarm_card_test.dart b/test/alarm/widgets/alarm_card_test.dart index 669f8b05..f38dacb9 100644 --- a/test/alarm/widgets/alarm_card_test.dart +++ b/test/alarm/widgets/alarm_card_test.dart @@ -4,6 +4,7 @@ import 'package:clock_app/common/types/time.dart'; import 'package:clock_app/theme/theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; const testKey = Key('key'); var sampleAlarm = Alarm(const Time(hour: 2, minute: 30)); @@ -88,6 +89,9 @@ void main() { Future _renderWidget(WidgetTester tester, [Alarm? alarm]) async { await tester.pumpWidget( MaterialApp( + locale: const Locale('en'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, theme: defaultTheme, home: Scaffold( body: AlarmCard( diff --git a/test/clock/widgets/time_display_test.dart b/test/clock/widgets/time_display_test.dart index d7c16c98..f246f745 100644 --- a/test/clock/widgets/time_display_test.dart +++ b/test/clock/widgets/time_display_test.dart @@ -3,6 +3,7 @@ import 'package:clock_app/theme/theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:intl/intl.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; void main() { testWidgets('TimeDisplay shows time correctly ...', (tester) async { @@ -10,6 +11,9 @@ void main() { String format = "hh:mm"; await tester.pumpWidget(MaterialApp( theme: defaultTheme, + locale: const Locale('en'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, home: TimeDisplay(format: format, fontSize: 32, dateTime: dateTime), )); diff --git a/test/clock/widgets/timezone_card_test.dart b/test/clock/widgets/timezone_card_test.dart index 698b31f1..f5937715 100644 --- a/test/clock/widgets/timezone_card_test.dart +++ b/test/clock/widgets/timezone_card_test.dart @@ -4,6 +4,7 @@ import 'package:clock_app/theme/theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:timezone/data/latest_all.dart' as timezone_db; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; bool deleted = false; const testKey = Key('key'); @@ -30,11 +31,14 @@ void main() { Future _renderWidget(WidgetTester tester) async { await tester.pumpWidget( MaterialApp( + locale: const Locale('en'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, theme: defaultTheme, home: TimeZoneCard( city: sampleCity, key: testKey, - onDelete: (){}, + onDelete: () {}, ), ), ); diff --git a/test/clock/widgets/timezone_search_card_test.dart b/test/clock/widgets/timezone_search_card_test.dart index d5e09910..6cd921e4 100644 --- a/test/clock/widgets/timezone_search_card_test.dart +++ b/test/clock/widgets/timezone_search_card_test.dart @@ -4,6 +4,7 @@ import 'package:clock_app/theme/theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:timezone/data/latest_all.dart' as timezone_db; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; var sampleCity = City("Tokyo", "Japan", "Asia/Tokyo"); @@ -35,6 +36,9 @@ void main() { Future _renderWidget(WidgetTester tester) async { await tester.pumpWidget( MaterialApp( + locale: const Locale('en'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, theme: defaultTheme, home: TimeZoneSearchCard( city: sampleCity, diff --git a/test/common/utils/weekday_utils_test.dart b/test/common/utils/weekday_utils_test.dart index c96aac55..79a335f9 100644 --- a/test/common/utils/weekday_utils_test.dart +++ b/test/common/utils/weekday_utils_test.dart @@ -6,25 +6,25 @@ void main() { group('weekdaysContains', () { test('returns true when the weekday is contained in the list', () { final testWeekdays = [weekdays[0]]; - expect(weekdaysContains(testWeekdays, 'Mon'), isTrue); + expect(weekdaysContains(testWeekdays, 1), isTrue); }); test('returns false when the weekday is not contained in the list', () { final testWeekdays = [weekdays[0]]; - expect(weekdaysContains(testWeekdays, 'Tue'), isFalse); + expect(weekdaysContains(testWeekdays, 2), isFalse); }); }); group('weekdaysContainsAll', () { test('returns true when all the weekdays are contained in the list', () { final testWeekdays = [weekdays[5], weekdays[6]]; - expect(weekdaysContainsAll(testWeekdays, ['Sat', 'Sun']), isTrue); + expect(weekdaysContainsAll(testWeekdays, [6, 7]), isTrue); }); test('returns false when at least one weekday is not contained in the list', () { final testWeekdays = [weekdays[4], weekdays[6]]; - expect(weekdaysContainsAll(testWeekdays, ['Sat', 'Mon']), isFalse); + expect(weekdaysContainsAll(testWeekdays, [6, 1]), isFalse); }); }); } diff --git a/test/common/widgets/fields/date_picker_field_test.dart b/test/common/widgets/fields/date_picker_field_test.dart index 51406f3b..369a9072 100644 --- a/test/common/widgets/fields/date_picker_field_test.dart +++ b/test/common/widgets/fields/date_picker_field_test.dart @@ -2,6 +2,7 @@ import 'package:clock_app/common/widgets/fields/date_picker_field.dart'; import 'package:clock_app/theme/theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; const title = 'Test'; const hintText = 'TestHint'; @@ -76,6 +77,9 @@ Future _renderWidget(WidgetTester tester, void Function(List)? onChanged}) async { await tester.pumpWidget( MaterialApp( + locale: const Locale('en'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, theme: defaultTheme, home: Scaffold( body: DatePickerField( diff --git a/test/common/widgets/fields/input_field_test.dart b/test/common/widgets/fields/input_field_test.dart index e1652e0a..3506d8ff 100644 --- a/test/common/widgets/fields/input_field_test.dart +++ b/test/common/widgets/fields/input_field_test.dart @@ -1,6 +1,7 @@ import 'package:clock_app/common/widgets/fields/input_field.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; const title = 'Test'; const hintText = 'TestHint'; @@ -108,6 +109,9 @@ Future _renderWidget(WidgetTester tester, {String value = "", void Function(String)? onChanged}) async { await tester.pumpWidget( MaterialApp( + locale: const Locale('en'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, home: Scaffold( body: InputField( value: value, diff --git a/test/common/widgets/fields/select_field_test.dart b/test/common/widgets/fields/select_field_test.dart index 947af00d..ca305c56 100644 --- a/test/common/widgets/fields/select_field_test.dart +++ b/test/common/widgets/fields/select_field_test.dart @@ -3,6 +3,7 @@ import 'package:clock_app/common/widgets/fields/select_field/option_cards/text_o import 'package:clock_app/common/widgets/fields/select_field/select_field.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; const title = 'Test'; final choices = [ @@ -140,11 +141,14 @@ Future _renderWidget(WidgetTester tester, {int selectedIndex = 0, void Function(List)? onChanged}) async { await tester.pumpWidget( MaterialApp( + locale: const Locale('en'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, home: Scaffold( body: SelectField( - selectedIndices: [selectedIndex], + getSelectedIndices: () => [selectedIndex], title: title, - choices: choices, + getChoices: () => choices, onChanged: onChanged ?? (_) {}, ), ), diff --git a/test/common/widgets/fields/slider_field_test.dart b/test/common/widgets/fields/slider_field_test.dart index 50227e32..04a5ae9e 100644 --- a/test/common/widgets/fields/slider_field_test.dart +++ b/test/common/widgets/fields/slider_field_test.dart @@ -1,6 +1,7 @@ import 'package:clock_app/common/widgets/fields/slider_field.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; const name = 'Test Slider'; const unit = 'unit'; @@ -37,6 +38,9 @@ Future _renderWidget(WidgetTester tester, {double value = 0, void Function(double)? onChanged}) async { await tester.pumpWidget( MaterialApp( + locale: const Locale('en'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, home: Scaffold( body: SliderField( value: value, diff --git a/test/common/widgets/fields/switch_field_test.dart b/test/common/widgets/fields/switch_field_test.dart index 27b66816..7ad75abd 100644 --- a/test/common/widgets/fields/switch_field_test.dart +++ b/test/common/widgets/fields/switch_field_test.dart @@ -1,6 +1,7 @@ import 'package:clock_app/common/widgets/fields/switch_field.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; const name = 'Test Switch'; @@ -67,6 +68,9 @@ Future _renderWidget(WidgetTester tester, {value = false, void Function(bool) onChanged = _defaultOnChanged}) async { await tester.pumpWidget( MaterialApp( + locale: const Locale('en'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, home: Scaffold( body: SwitchField( name: name, diff --git a/test/common/widgets/fields/toggle_field_test.dart b/test/common/widgets/fields/toggle_field_test.dart index 5ae7ec31..4670505b 100644 --- a/test/common/widgets/fields/toggle_field_test.dart +++ b/test/common/widgets/fields/toggle_field_test.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:clock_app/common/widgets/fields/toggle_field.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; const List> testOptions = [ ToggleOption('Option 1', 1), @@ -56,6 +57,9 @@ Future _renderWidget(WidgetTester tester, void Function(int)? onChange}) async { await tester.pumpWidget( MaterialApp( + locale: const Locale('en'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, home: Scaffold( body: ToggleField( name: name ?? 'Test Field', diff --git a/test/common/widgets/time_picker_test.dart b/test/common/widgets/time_picker_test.dart index 4ce8224a..a3d017b2 100644 --- a/test/common/widgets/time_picker_test.dart +++ b/test/common/widgets/time_picker_test.dart @@ -2,6 +2,7 @@ import 'package:clock_app/common/types/picker_result.dart'; import 'package:clock_app/common/widgets/time_picker.dart'; import 'package:flutter/material.dart' hide TimePickerDialog; import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; TimeOfDay selectedTime = const TimeOfDay(hour: 12, minute: 30); @@ -126,6 +127,9 @@ void main() { Future _renderWidget(WidgetTester tester) async { return await tester.pumpWidget( MaterialApp( + locale: const Locale('en'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, home: Scaffold( body: Builder( builder: (BuildContext context) { diff --git a/test/theme/widgets/theme_card_test.dart b/test/theme/widgets/theme_card_test.dart index b2ca262d..3c23b1b4 100644 --- a/test/theme/widgets/theme_card_test.dart +++ b/test/theme/widgets/theme_card_test.dart @@ -6,6 +6,7 @@ import 'package:clock_app/theme/utils/style_theme.dart'; import 'package:clock_app/theme/widgets/theme_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; const testKey = Key('key'); var sampleStyleTheme = StyleTheme(); @@ -74,6 +75,9 @@ Future _renderStyleThemeCard(WidgetTester tester, await tester.pumpWidget( MaterialApp( theme: defaultTheme, + locale: const Locale('en'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, home: Scaffold( body: ThemeCard( themeItem: sampleStyleTheme, @@ -81,7 +85,8 @@ Future _renderStyleThemeCard(WidgetTester tester, onPressDelete: () {}, onPressDuplicate: () {}, onPressEdit: () {}, - getThemeFromItem: (theme, item) => getTheme(colorScheme:theme.colorScheme, styleTheme: item), + getThemeFromItem: (theme, item) => + getTheme(colorScheme: theme.colorScheme, styleTheme: item), key: testKey, ), ), diff --git a/test/theme/widgets/theme_preview_card_test.dart b/test/theme/widgets/theme_preview_card_test.dart index 161bb16d..02cab6f5 100644 --- a/test/theme/widgets/theme_preview_card_test.dart +++ b/test/theme/widgets/theme_preview_card_test.dart @@ -3,6 +3,7 @@ import 'package:clock_app/theme/theme.dart'; import 'package:clock_app/theme/widgets/theme_preview_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; const testKey = Key('key'); var defaultColorScheme = defaultTheme.colorScheme; @@ -70,6 +71,9 @@ Future _renderStyleThemeCard(WidgetTester tester) async { await tester.pumpWidget( MaterialApp( theme: defaultTheme, + locale: const Locale('en'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, home: const Scaffold( body: ThemePreviewCard( key: testKey, diff --git a/test/timer/widgets/timer_card_test.dart b/test/timer/widgets/timer_card_test.dart index 415eadc9..d7a3da20 100644 --- a/test/timer/widgets/timer_card_test.dart +++ b/test/timer/widgets/timer_card_test.dart @@ -4,6 +4,7 @@ import 'package:clock_app/timer/widgets/timer_card.dart'; import 'package:clock_app/theme/theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; const testKey = Key('key'); var sampleTimer = @@ -78,14 +79,17 @@ Future _renderWidget(WidgetTester tester, [ClockTimer? timer]) async { await tester.pumpWidget( MaterialApp( theme: defaultTheme, + locale: const Locale('en'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, home: Scaffold( body: TimerCard( timer: timer ?? sampleTimer, onToggleState: () {}, onPressDelete: () {}, onPressDuplicate: () {}, - onPressReset: (){}, - onPressAddTime: (){}, + onPressReset: () {}, + onPressAddTime: () {}, key: testKey, ), ),