Compare commits

...
18 Commits
Author SHA1 Message Date
Jean-Luc Makiola 7be6b7ac31 Release v2.20.3 (#302)
Release — F-Droid repo + Gitea/Codeberg release + Play / play (push) Successful in 57s
Release — F-Droid repo + Gitea/Codeberg release + Play / detect (push) Successful in 6s
Release — F-Droid repo + Gitea/Codeberg release + Play / release (push) Successful in 12m49s
2026-09-12 17:09:15 +02:00
Jean-Luc Makiola 20c20b71ea Release v2.20.2 (#299)
Release — F-Droid repo + Gitea/Codeberg release + Play / release (push) Failing after 7m20s
Release — F-Droid repo + Gitea/Codeberg release + Play / play (push) Skipped
Release — F-Droid repo + Gitea/Codeberg release + Play / detect (push) Successful in 7s
2026-09-12 15:49:04 +02:00
Jean-Luc Makiola 0fb3df0b3a Merge pull request 'Translations update from Weblate' (#262) from jlmakiola_weblate_bot/calendula:weblate-calendula-strings into main
Release — F-Droid repo + Gitea/Codeberg release + Play / detect (push) Successful in 15s
Release — F-Droid repo + Gitea/Codeberg release + Play / release (push) Skipped
Release — F-Droid repo + Gitea/Codeberg release + Play / play (push) Skipped
2026-09-12 15:23:25 +02:00
Weblate e10b09a9b5 Translated using Weblate (Arabic)
Currently translated at 100.0% (593 of 593 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/ar/
2026-09-12 02:29:58 +00:00
Sup99999 806a576380 Translated using Weblate (Arabic)
Currently translated at 100.0% (593 of 593 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/ar/
2026-09-12 02:29:58 +00:00
James Trivette 3c365c6792 Translated using Weblate (Czech)
Currently translated at 71.1% (422 of 593 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/cs/
2026-09-11 19:34:07 +00:00
Andrei Linchik 4fb4a85ac4 Translated using Weblate (Russian)
Currently translated at 42.4% (252 of 593 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/ru/
2026-09-11 19:34:07 +00:00
Benutzer e7312e5d6e Translated using Weblate (Italian)
Currently translated at 98.6% (585 of 593 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/it/
2026-09-11 19:34:07 +00:00
Sup99999 12c2de7ed8 Translated using Weblate (Arabic)
Currently translated at 99.1% (588 of 593 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/ar/
2026-09-11 19:34:07 +00:00
António de Seabra 8a3cc95c66 Translated using Weblate (Portuguese)
Currently translated at 76.8% (456 of 593 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/pt/
2026-09-11 19:34:07 +00:00
James Trivette 9c06ffdb48 Translated using Weblate (Czech)
Currently translated at 66.1% (392 of 593 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/cs/
2026-09-11 19:34:07 +00:00
James Trivette 870a903015 Translated using Weblate (Czech)
Currently translated at 60.6% (353 of 582 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/cs/
2026-09-11 19:34:07 +00:00
Sup99999 b5768e3b17 Translated using Weblate (Arabic)
Currently translated at 99.1% (577 of 582 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/ar/
2026-09-11 19:34:07 +00:00
Dmitri Gabinski 02b33dbf07 Translated using Weblate (Belarusian)
Currently translated at 98.7% (567 of 574 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/be/
2026-09-11 19:34:07 +00:00
Jean-Luc Makiola a0c0b875f0 Move the privacy policy into the repo (#293)
Release — F-Droid repo + Gitea/Codeberg release + Play / detect (push) Successful in 6s
Release — F-Droid repo + Gitea/Codeberg release + Play / release (push) Skipped
Release — F-Droid repo + Gitea/Codeberg release + Play / play (push) Skipped
Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/293
2026-09-09 16:23:47 +02:00
makiolaj 512bf8c746 docs: shape the policy as the content entry the site renders
Frontmatter carries the title, description and date, the body starts at
the first section rather than repeating the title as an h1, and the
maintainer note is an HTML comment — a blockquote would have rendered
"edit this in a PR" onto the published privacy page.
2026-09-09 16:14:42 +02:00
makiolaj 04257e8a66 docs: the privacy policy moves into the repo
The policy lived only as prose inside the website's Astro page, so it was
the one user-facing document with no review, no history here, and no way
to change it alongside the code that makes it true.

docs/PRIVACY.md is now that text, transcribed from the published page so
the wording is unchanged, and it becomes the source: the site's build
checks this repository out beside itself and renders this file through an
Astro content collection rather than keeping its own copy. One copy of the
policy exists anywhere, so the two cannot drift.

The README links it from Documentation and gains a Privacy section beside
License. Agendula is being set up the same way.
2026-09-09 16:13:42 +02:00
Jean-Luc Makiolaandmakiolaj c04b2ecee2 Release v2.20.1 (#288)
Release — F-Droid repo + Gitea/Codeberg release + Play / detect (push) Successful in 8s
Release — F-Droid repo + Gitea/Codeberg release + Play / release (push) Successful in 31m27s
Release — F-Droid repo + Gitea/Codeberg release + Play / play (push) Successful in 1m22s
Release 2.20.1.

**Fixed**

- "No calendars configured" offered an "Open system calendar settings" button that opened nothing — every screen wired it to the same reload that had just produced the empty state. It now opens the system's account chooser, filtered to the providers that sync calendars ([#239]).
- A device whose calendars are all switched off no longer looks like an empty month. The app only ever checked whether the device had *no* calendars, so calendars hidden at system level fell through to a blank grid with no hint. That case now says so and points at Settings → Calendars. The navigation drawer's calendar list drew the same conflation and is fixed with it ([#239]).

**Beyond the issue**

Two things in here aren't part of #239:

- `fastlane/metadata/android/en-US/changelogs/22001.txt` carries the 2.20.0 notes as well as 2.20.1's. The 2.20.0 Play upload failed on a service-account permission (it lacked "Release to production"; 2.19.4 failed the same way), so Play is still on 2.19.3 and users jump straight to 2.20.1. Left alone they would have seen only the 2.20.1 bugfixes and never heard about the hour grid, copyable event fields or invitation outlines. 402 characters, inside Play's 500 limit. The permission has since been granted, so this release should be the one that lands.
- A merge of `main` into the branch. `main` took 2.20.0 as a squash, so the two had no common ancestor past 2.19.4 and this PR would otherwise have replayed all 74 files of 2.20.0. Resolved to the branch throughout; the tree is byte-for-byte unchanged by it.

Closes #239.

Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de>
Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/288
2026-09-07 22:29:03 +02:00
46 changed files with 1203 additions and 104 deletions
+39
View File
@@ -5,6 +5,42 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.20.3] — 2026-09-12
### Fixed
- **A custom agenda range crashed the app in French.** Choosing a custom range
for the agenda — or simply typing a number into that field — closed the app on
any phone set to French. The French translation of the "%d days" label was
missing the wording French uses for counts of two and above, and Android has
nothing to fall back on when that particular form is absent, so every value
except one day was affected ([#297], [#298]).
## [2.20.2] — 2026-09-12
### Fixed
- **Crash reports are filed in English.** Reporting a crash from a phone set to
another language prefilled the issue — title and body — in that language, so
a French crash arrived on Codeberg as a French issue ([#297], [#298]). The
text that is *posted* is now English for everyone; the dialog that asks you
to send it, and everything else you see in the app, is still translated.
## [2.20.1] — 2026-09-07
### Fixed
- **An empty calendar now explains itself.** "No calendars configured" offered
an "Open system calendar settings" button that opened nothing — every screen
wired it to the same reload that had just produced the empty state. It now
opens the system's account chooser, filtered to the providers that sync
calendars ([#239]).
- **Calendars that are all switched off no longer look like an empty month.**
When every calendar on the device is hidden at system level there is nothing
to draw, but the app said nothing at all: it only ever checked whether the
device had *no* calendars, so a device that had them and hid them fell
through to a blank grid with no hint. That case now says so, and points at
Settings → Calendars — the one screen that can switch a calendar back on. The
navigation drawer's calendar list drew the same conflation and is fixed with
it ([#239]).
## [2.20.0] — 2026-09-07
### Added
@@ -1654,3 +1690,6 @@ automatically, with zero telemetry and no internet permission.
[#150]: https://codeberg.org/jlmakiola/calendula/issues/150
[#146]: https://codeberg.org/jlmakiola/calendula/issues/146
[#267]: https://codeberg.org/jlmakiola/calendula/issues/267
[#239]: https://codeberg.org/jlmakiola/calendula/issues/239
[#297]: https://codeberg.org/jlmakiola/calendula/issues/297
[#298]: https://codeberg.org/jlmakiola/calendula/issues/298
+12
View File
@@ -157,6 +157,8 @@ reinstalling. Google Play is the exception — see above.</sub>
- **[Building from source](docs/BUILDING.md)** — requirements and Gradle tasks
- **[Architecture](docs/ARCHITECTURE.md)** — the layered design and key pipelines
- **[Milestones](https://codeberg.org/jlmakiola/calendula/milestones)** — what's shipped and what's next
- **[Privacy policy](docs/PRIVACY.md)** — the source of the page published at
[jeanlucmakiola.de/calendula/privacy](https://jeanlucmakiola.de/calendula/privacy)
## 🤝 Contributing
@@ -187,6 +189,16 @@ No coding needed — register on the Weblate server, pick (or request) a languag
and translate the strings in your browser. You can also reach this link in the
app from the top of **Settings → App language**.
## 🔒 Privacy
No analytics, no tracking, no advertising, no crash-reporting SDK, no third-party
services — and **no internet permission at all**, so the app is technically
incapable of transmitting anything anywhere. Your events stay in Android's own
calendar store, where they already were.
**→ [Privacy policy](https://jeanlucmakiola.de/calendula/privacy)** — written in
[`docs/PRIVACY.md`](docs/PRIVACY.md), which is what that page renders.
## 📜 License
[MIT](LICENSE) — Jean-Luc Makiola, 2026
+12 -8
View File
@@ -28,8 +28,8 @@ android {
// which builds this version and then creates the matching vX.Y.Z tag +
// release itself (versionCode is pinned to MAJOR*10000 + MINOR*100 +
// PATCH from versionName, e.g. 2.7.2 -> 20702). See docs/RELEASING.md.
versionCode = 22000
versionName = "2.20.0"
versionCode = 22003
versionName = "2.20.3"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
@@ -113,12 +113,16 @@ android {
lint {
// Community translations are expected to be partial — a missing string
// falls back to the English base at runtime — so don't fail the build on
// it. Likewise a translated <plurals> may not fill every CLDR quantity
// form its locale defines (e.g. Arabic needs "zero"); the missing form
// falls back to "other" at runtime, so MissingQuantity is informational
// too. Stale/extra keys (ExtraTranslation) stay fatal; scripts/
// check_translations.py guards the same invariants with clearer,
// translator-facing messages.
// it. A translated <plurals> may likewise skip a CLDR quantity form its
// locale defines (e.g. Arabic "zero"): Android falls back to "other" for
// any form it cannot find, so MissingQuantity is informational too.
// What a translation must NOT skip is "other" itself — nothing falls back
// for that one, not even the base locale, so it throws
// Resources$NotFoundException at runtime (Codeberg #297/#298).
// MissingQuantity doesn't tell the two cases apart, so that invariant is
// enforced by scripts/check_translations.py instead, with a clearer
// translator-facing message. Stale/extra keys (ExtraTranslation) stay
// fatal.
informational += listOf("MissingTranslation", "MissingQuantity")
}
@@ -32,13 +32,15 @@ class CalendulaApp : Application() {
// respecting, on-device; the user submits the report by hand). The
// capture/loop-detection/report machinery lives in floret-kit's
// core-crash; only the app label + issue-tracker URLs are app-specific.
// The prefilled issue's own title and body are the kit's, in English:
// they are posted to the tracker, so they don't follow the device
// language the way the dialog around them does.
CrashReporter.install(
this,
CrashConfig(
appLabel = getString(R.string.app_name),
newIssueUrl = getString(R.string.report_issue_url),
chooseIssueUrl = getString(R.string.report_issue_choose_url),
issueTitle = getString(R.string.crash_report_issue_title),
),
)
reconcileAutoBackup()
@@ -46,3 +46,19 @@ fun hasSystemHiddenCalendars(
calendars: List<CalendarSource>,
pendingDisabledIds: Set<Long>,
): Boolean = calendars.any { !it.isVisibleInSystem && it.id !in pendingDisabledIds }
/**
* The failure a calendar list implies, or null when there is something to show.
* Distinguishes "the device has no calendars" from "every one of them is
* switched off" (#239) — both leave the grid empty, but only the second is
* fixed from Settings → Calendars.
*
* The filter sheet's own hidden set is deliberately not folded in: emptying it
* is a deliberate act taken moments earlier, in a sheet that is still one tap
* away.
*/
fun calendarListFailure(calendars: List<CalendarSource>): FailureReason? = when {
calendars.isEmpty() -> FailureReason.NoCalendarsConfigured
calendars.none { it.isVisibleInSystem } -> FailureReason.AllCalendarsHidden
else -> null
}
@@ -252,6 +252,7 @@ enum class RecurringWriteScope {
enum class FailureReason {
PermissionRevoked,
NoCalendarsConfigured,
AllCalendarsHidden,
ProviderUnavailable,
EventNotFound,
Unknown,
@@ -31,6 +31,7 @@ import de.jeanlucmakiola.calendula.ui.common.CalendarView
import de.jeanlucmakiola.calendula.ui.common.EventMoveHost
import de.jeanlucmakiola.calendula.ui.common.EventMoveScope
import de.jeanlucmakiola.calendula.ui.common.LocalEventMove
import de.jeanlucmakiola.calendula.ui.common.LocalManageCalendars
import de.jeanlucmakiola.calendula.ui.common.RescheduleViewModel
import de.jeanlucmakiola.calendula.ui.common.drillToDay
import de.jeanlucmakiola.calendula.ui.common.rememberCalendarSlideSpec
@@ -344,7 +345,12 @@ fun CalendarHost(
// navigation, so it fades through rather than sliding — paging *within* a
// view keeps the directional slide. AnimatedContent keyed on the view type.
val viewSwitch = fadeThrough()
CompositionLocalProvider(LocalEventMove provides moveScope) {
CompositionLocalProvider(
LocalEventMove provides moveScope,
// The failure state's way out when every calendar is switched off
// (#239); nothing else in the calendar surfaces navigates here.
LocalManageCalendars provides { showCalendars = true },
) {
AnimatedContent(
targetState = view,
transitionSpec = { viewSwitch },
@@ -11,6 +11,7 @@ import de.jeanlucmakiola.calendula.data.prefs.firstDayOfWeek
import de.jeanlucmakiola.calendula.domain.CalendarSource
import de.jeanlucmakiola.calendula.domain.EventInstance
import de.jeanlucmakiola.calendula.domain.FailureReason
import de.jeanlucmakiola.calendula.domain.calendarListFailure
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
@@ -156,9 +157,7 @@ class AgendaViewModel @Inject constructor(
calendars: List<CalendarSource>,
instances: List<EventInstance>,
): AgendaUiState {
if (calendars.isEmpty()) {
return AgendaUiState.Failure(FailureReason.NoCalendarsConfigured)
}
calendarListFailure(calendars)?.let { return AgendaUiState.Failure(it) }
val anchor = params.anchor
val rangeEnd = anchor.plus(
params.range.dayCount(anchor, params.weekStart) - 1,
@@ -1,5 +1,9 @@
package de.jeanlucmakiola.calendula.ui.common
import android.content.Context
import android.content.Intent
import android.provider.CalendarContract
import android.provider.Settings
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
@@ -10,8 +14,10 @@ import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
@@ -24,18 +30,29 @@ import de.jeanlucmakiola.calendula.domain.FailureReason
*/
@Composable
fun CalendarFailure(reason: FailureReason, onRetry: () -> Unit) {
val context = LocalContext.current
val manageCalendars = LocalManageCalendars.current
val titleRes = when (reason) {
FailureReason.PermissionRevoked -> R.string.state_failure_permission
FailureReason.NoCalendarsConfigured -> R.string.state_failure_no_calendars
FailureReason.AllCalendarsHidden -> R.string.state_failure_all_hidden
FailureReason.ProviderUnavailable -> R.string.state_failure_provider
FailureReason.Unknown,
FailureReason.EventNotFound -> R.string.state_failure_unknown
}
val actionRes = when (reason) {
FailureReason.NoCalendarsConfigured -> R.string.state_failure_no_calendars_action
FailureReason.AllCalendarsHidden -> R.string.state_failure_all_hidden_action
FailureReason.PermissionRevoked -> R.string.state_failure_permission_action
else -> R.string.state_retry
}
val onAction: () -> Unit = when (reason) {
FailureReason.NoCalendarsConfigured -> {
{ context.startCalendarSetup() }
}
FailureReason.AllCalendarsHidden -> manageCalendars ?: onRetry
else -> onRetry
}
Column(
modifier = Modifier
.fillMaxSize()
@@ -49,8 +66,30 @@ fun CalendarFailure(reason: FailureReason, onRetry: () -> Unit) {
textAlign = TextAlign.Center,
)
Spacer(Modifier.height(24.dp))
FilledTonalButton(onClick = onRetry) {
FilledTonalButton(onClick = onAction) {
Text(stringResource(actionRes))
}
}
}
/**
* Opens Settings → Calendars, the only screen that can switch a calendar back
* on. Null outside the calendar host — screens without it never raise the
* reason that needs it, and fall back to their own retry.
*/
val LocalManageCalendars = compositionLocalOf<(() -> Unit)?> { null }
/**
* Open the system screen for putting a calendar on the device: the account
* chooser filtered to calendar providers, falling back to account settings
* where no chooser resolves. Both are system components, so nothing here needs
* a `<queries>` entry.
*/
private fun Context.startCalendarSetup() {
val intents = listOf(
Intent(Settings.ACTION_ADD_ACCOUNT)
.putExtra(Settings.EXTRA_AUTHORITIES, arrayOf(CalendarContract.AUTHORITY)),
Intent(Settings.ACTION_SYNC_SETTINGS),
)
intents.firstOrNull { runCatching { startActivity(it) }.isSuccess }
}
@@ -8,6 +8,7 @@ import de.jeanlucmakiola.calendula.data.di.IoDispatcher
import de.jeanlucmakiola.calendula.domain.CalendarSource
import de.jeanlucmakiola.calendula.domain.EventInstance
import de.jeanlucmakiola.calendula.domain.FailureReason
import de.jeanlucmakiola.calendula.domain.calendarListFailure
import de.jeanlucmakiola.calendula.ui.week.layoutAllDay
import de.jeanlucmakiola.calendula.ui.week.layoutDay
import kotlinx.coroutines.CoroutineDispatcher
@@ -88,9 +89,7 @@ class DayViewModel @Inject constructor(
calendars: List<CalendarSource>,
instances: List<EventInstance>,
): DayUiState {
if (calendars.isEmpty()) {
return DayUiState.Failure(FailureReason.NoCalendarsConfigured)
}
calendarListFailure(calendars)?.let { return DayUiState.Failure(it) }
val days = listOf(day)
val allDay = instances.filter { it.isAllDay }
val timed = instances.filterNot { it.isAllDay }
@@ -125,6 +125,7 @@ private fun FilterLoading(modifier: Modifier = Modifier) {
private fun FilterMessage(reason: FailureReason, modifier: Modifier = Modifier) {
val msg = when (reason) {
FailureReason.NoCalendarsConfigured -> R.string.state_failure_no_calendars
FailureReason.AllCalendarsHidden -> R.string.state_failure_all_hidden
FailureReason.PermissionRevoked -> R.string.state_failure_permission
else -> R.string.state_failure_provider
}
@@ -8,6 +8,7 @@ import de.jeanlucmakiola.calendula.data.di.IoDispatcher
import de.jeanlucmakiola.calendula.data.prefs.CalendarPrefs
import de.jeanlucmakiola.calendula.domain.CalendarSource
import de.jeanlucmakiola.calendula.domain.FailureReason
import de.jeanlucmakiola.calendula.domain.calendarListFailure
import de.jeanlucmakiola.calendula.ui.common.groupByAccount
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.SharingStarted
@@ -35,8 +36,9 @@ class FilterViewModel @Inject constructor(
// Calendars switched off device-wide don't belong in the drawer's
// hide/show list; they live only in Settings → Calendars.
val enabled = calendars.filter { it.isVisibleInSystem }
if (enabled.isEmpty()) {
FilterUiState.Failure(FailureReason.NoCalendarsConfigured)
val failure = calendarListFailure(calendars)
if (failure != null) {
FilterUiState.Failure(failure)
} else {
FilterUiState.Success(groupCalendarsForFilter(enabled, hidden))
}
@@ -10,6 +10,7 @@ import de.jeanlucmakiola.calendula.data.prefs.firstDayOfWeek
import de.jeanlucmakiola.calendula.domain.CalendarSource
import de.jeanlucmakiola.calendula.domain.EventInstance
import de.jeanlucmakiola.calendula.domain.FailureReason
import de.jeanlucmakiola.calendula.domain.calendarListFailure
import de.jeanlucmakiola.calendula.domain.isDeclined
import de.jeanlucmakiola.calendula.ui.week.coversDay
import de.jeanlucmakiola.calendula.ui.week.layoutAllDay
@@ -208,9 +209,7 @@ class MonthViewModel @Inject constructor(
calendars: List<CalendarSource>,
instances: List<EventInstance>,
): ContinuousMonthUiState {
if (calendars.isEmpty()) {
return ContinuousMonthUiState.Failure(FailureReason.NoCalendarsConfigured)
}
calendarListFailure(calendars)?.let { return ContinuousMonthUiState.Failure(it) }
// Bucketed once for the whole window: a row then takes the handful of
// events on its seven days instead of re-scanning a year of them.
val byDay = DayIndex(instances, zone)
@@ -314,9 +313,7 @@ class MonthViewModel @Inject constructor(
calendars: List<CalendarSource>,
instances: List<EventInstance>,
): MonthUiState {
if (calendars.isEmpty()) {
return MonthUiState.Failure(FailureReason.NoCalendarsConfigured)
}
calendarListFailure(calendars)?.let { return MonthUiState.Failure(it) }
val weeks = layoutMonthWeeks(ym, weekStart, instances, zone)
return MonthUiState.Success(
month = ym,
@@ -10,6 +10,7 @@ import de.jeanlucmakiola.calendula.data.prefs.resolveFirstDay
import de.jeanlucmakiola.calendula.domain.CalendarSource
import de.jeanlucmakiola.calendula.domain.EventInstance
import de.jeanlucmakiola.calendula.domain.FailureReason
import de.jeanlucmakiola.calendula.domain.calendarListFailure
import de.jeanlucmakiola.calendula.domain.isDeclined
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -126,9 +127,7 @@ class WeekViewModel @Inject constructor(
calendars: List<CalendarSource>,
instances: List<EventInstance>,
): WeekUiState {
if (calendars.isEmpty()) {
return WeekUiState.Failure(FailureReason.NoCalendarsConfigured)
}
calendarListFailure(calendars)?.let { return WeekUiState.Failure(it) }
val days = (0 until 7).map { start.plus(it, DateTimeUnit.DAY) }
val allDay = instances.filter { it.isAllDay }
val timed = instances.filterNot { it.isAllDay }
+52 -22
View File
@@ -43,16 +43,16 @@
<string name="event_detail_edit">تعديل</string>
<string name="event_detail_delete">حذف</string>
<string name="event_detail_share">مشاركة</string>
<string name="event_detail_duplicate">نسخ</string>
<string name="event_detail_duplicate">تكرار</string>
<string name="event_share_chooser_title">مشاركة الحدث</string>
<string name="day_today_action">اليوم</string>
<string name="week_today_action">هذا الأسبوع</string>
<string name="week_number_label">أسبوع</string>
<string name="event_detail_back">العودة</string>
<string name="event_detail_back">الرجوع</string>
<string name="month_a11y_today_prefix">اليوم</string>
<string name="event_share_failed">تعذّر مشاركة هذا الحدث.</string>
<string name="event_delete_title">حذف الحدث؟</string>
<string name="event_delete_body">الحدث أُزيل من تقويمك ومن كل جهاز تتم مزامنته معه.</string>
<string name="event_delete_body">تتم إزالة الحدث من تقويمك ومن كل جهاز تتم مزامنته معه.</string>
<string name="event_delete_recurring_title">حذف الحدث المتكرّر</string>
<string name="event_delete_option_occurrence">فقط هذا الحدث</string>
<string name="event_delete_option_following">هذا وجميع الأحداث اللاحقة</string>
@@ -172,7 +172,7 @@
<string name="event_attendee_optional">اختياري</string>
<string name="reminder_default">التذكير الافتراضي</string>
<string name="event_detail_self_response">ردَّك: %1$s</string>
<string name="event_attendee_resource">المُنسِّق</string>
<string name="event_attendee_resource">المُورِّد</string>
<string name="reminder_at_time">في وقت الحدث</string>
<string name="event_untitled">(بدون عنوان)</string>
<string name="reminder_channel_name">تذكيرات الحدث</string>
@@ -319,8 +319,8 @@
<string name="settings_theme_hint">سواء التطبيق فاتحًا أو داكنًا. الاختيار يُطبق على الفور.</string>
<string name="settings_week_start_auto_summary">الحالي %1$s</string>
<string name="settings_time_format_auto_summary">اتباع النظام: %1$s</string>
<string name="settings_hour_lines">خطوط الساعات</string>
<string name="settings_hour_lines_summary">إظهار خط فاصل في كل ساعة في طريقة عرض الأسبوع واليوم</string>
<string name="settings_hour_lines">شبكة الساعة</string>
<string name="settings_hour_lines_summary">وضع كل ساعة في خانتها الخاصة في طريقة عرض الأسبوع واليوم</string>
<string name="timeline_scale_fit_day_summary">جميع الـ 24 ساعة على شاشة واحدة، لا تمرير</string>
<string name="timeline_scale_custom">مخصص</string>
<string name="settings_widget_size_small">صغير</string>
@@ -341,12 +341,12 @@
<string name="month_style_continuous">تمرير الشهور</string>
<string name="month_style_dense">أسابيع سلسة</string>
<string name="month_style_continuous_summary">كل شهر يقع تحت عنوانه الخاص، مع مساحة صغيرة تميزه عن الشهر التالي.</string>
<string name="month_style_dense_summary">تمر الأسابيع دون انقطاع، ويتدفق كل شهر مباشرة إلى الشهر التالي دون وجود فجوة بينهما.</string>
<string name="month_style_dense_summary">تتوالى الأسابيع دون انقطاع، وينساب كل شهر مباشرة إلى التالي دون وجود فجوة بينهم.</string>
<string name="month_split_no_events">لا شيء مجدول</string>
<string name="month_style_split_summary">شبكة مدمجة تحدد الأيام التي تتضمن أحداثًا، ويتم إدراج اليوم الذي تنقر عليه تحتها.</string>
<string name="settings_autofocus_title">تركيز العنوان على حدث جديد</string>
<string name="settings_event_duration">المدة الافتراضية</string>
<string name="settings_event_duration_hint">مدة الحدث الجديد تبقى كما هي حتى أنت تغيير وقت نهايته. أما أحداث التي هي طوال اليوم فلن تتأثر.</string>
<string name="settings_event_duration_hint">كم مدة استمرار حدث جديد إلى أي تقوم بتغيير وقت انتهائه. لا تتأثر أحداث طوال اليوم.</string>
<string name="settings_section_notifications">الإشعارات</string>
<string name="settings_reminders_hint">ترى التذكيرات مرتين؟ هناك تطبيق تقويم آخر ينشرهم أيضًا — قم بإيقافهم في أحد من الاثنين.</string>
<string name="settings_group_look">المظهر و السلوك</string>
@@ -361,7 +361,6 @@
<string name="settings_about_support">دَعم التطوير</string>
<string name="settings_about_version">الإصدار %1$s</string>
<string name="settings_about_logo_desc">رمز تطبيق Calendula</string>
<string name="crash_report_body_template">شكرًا لإبلاغ عن عطل في %1$s. يُرجى إضافة أي شيء تتذكره حول ما كنت تفعله، ثم إرسال.\n\n### ماذا حدث\n\n\n### تقرير العطل\n%2$s\n</string>
<string name="settings_section_about">حول</string>
<string name="settings_report_problem">الإبلاغ عن مشكلة</string>
<string name="settings_report_problem_hint">أرسل تقرير الأعطال أو افتح متعقب المشكلات</string>
@@ -375,7 +374,7 @@
<string name="shortcut_new_event_short">حدث جديد</string>
<string name="settings_qs_tile_hint">أضف مربع ”حدث جديد“ إلى لوحة الإعدادات السريعة.</string>
<string name="calendars_local_header">تقويماتك</string>
<string name="settings_section_special_dates">تواريخ جهات الاتصال الخاصة</string>
<string name="settings_section_special_dates">التواريخ الخاصة لجهات الاتصال</string>
<string name="calendars_title">التقويمات</string>
<string name="calendars_add">إضافة تقويم</string>
<string name="settings_section_calendars">التقويمات</string>
@@ -492,7 +491,7 @@
<string name="calendars_local_empty">لا تقويمات محلية حتى الآن. أنشئ واحدًا للاحتفاظ بالأحداث على هذا الجهاز فقط.</string>
<string name="calendars_auto_backup_interval">الفاصل الزمني</string>
<string name="import_warning_no_start">تم تخطي حدث بدون وقت بدء.</string>
<string name="import_warning_recurrence">تم تخطي بعض التكرارات التي تم تغييرها للأحداث المتكررة.</string>
<string name="import_warning_recurrence">تم تخطي بعض التكرارات المعدلة للأحداث المتكررة.</string>
<string name="import_close">إغلاق</string>
<string name="import_done_skipped_label">التكرارات</string>
<string name="import_done_added_label">أُضيف</string>
@@ -502,9 +501,7 @@
<string name="crash_dialog_dismiss">ليس الآن</string>
<string name="crash_report_copied">تم نسخ التقرير إلى حافظتك</string>
<string name="crash_report_open_failed">تعذّر فتح متتبع المشكلات. التقرير موجود في حافظتك.</string>
<string name="crash_report_issue_title">تقرير العطل</string>
<string name="crash_report_clip_label">%1$s تقرير العطل</string>
<string name="crash_report_body_paste">_(كان التقرير طويلًا جدًا لهذا الرابط — الصقه من حافظتك هنا.)_</string>
<string name="special_dates_calendar_birthday">أعياد الميلاد</string>
<string name="special_dates_calendar_custom">التواريخ الخاصة</string>
<string name="event_edit_recurrence_next_none">هذه القاعدة لا تتكرر أبدًا</string>
@@ -556,7 +553,7 @@
<string name="event_move_write_denied">Calendula يحتاج إلى صلاحية للكتابة لنقل الأحداث</string>
<string name="event_move_gone">لم يعد هذا الحدث موجودًا</string>
<string name="onboarding_step_counter">الخطوة %1$d من %2$d</string>
<string name="onboarding_backup_title">أحداثك تعيش فقط هنا</string>
<string name="onboarding_backup_title">أحداثك تعيش هنا فقط</string>
<string name="onboarding_backup_body">لا شئ على هذا الهاتف تتم مزامنته لحساب، لذلك فقدانها سيؤدي لفقدان تقويمك. Calendula يمكنه كتابة نسخة احتياطية لك.</string>
<string name="onboarding_backup_benefit_folder_body">النسخ الاحتياطية هي ملفات .ics عادية — ضعها في مكان ما يزامن، أو على بطاقة SD.</string>
<string name="onboarding_backup_benefit_daily_title">مرة واحدة يوميًا، من تلقاء نفسه</string>
@@ -663,7 +660,7 @@
<string name="settings_drag_to_reschedule_summary">انقل حدثًا عن طريق سحبه إلى يوم أو وقت آخر</string>
<string name="event_move_blocked_series_end">لا يمكن نقل حدث بعد نهاية سلسلته</string>
<string name="crash_dialog_report">تقرير</string>
<string name="settings_quick_switch_hint">اختر أي طُرق العرض التي يتم التنقل بينها باستخدام الزر في أعلى اليمين، واسحب لإعادة ترتيبهم. تظل طُرق العرض التي تم إيقافها متاحة من قائمة التنقل.</string>
<string name="settings_quick_switch_hint">اختر أي طُرق العرض التي يتم التنقل بينها باستخدام الزر في أعلى اليمين، واسحب لإعادة ترتيبهم. مع تشغيل أقل من عرضين اثنين يكون الزر مخفيًا. تظل طُرق العرض التي تم إيقافها متاحة من قائمة التنقل.</string>
<string name="calendars_account_from_source">%1$s (%2$s)</string>
<string name="duration_hours_minutes">%1$s %2$s</string>
<string name="settings_widgets_hint">إعدادات لأدوات الشاشة الرئيسية وعنصر الإعدادات السريعة. أضف أداة عن طريق الضغط لفترة طويلة على شاشتك الرئيسية.</string>
@@ -683,8 +680,8 @@
<string name="settings_font_specimen_body">مراجعة الفريق في 10:00، ثم الغداء مع روبن في المقهى في ماركتبلاتز.</string>
<string name="settings_section_widgets">الأدوات المصغّرة والعناصر</string>
<string name="settings_widget_size_hint">مدى حجم النص الذي يعرضه جدول أداة الشاشة الرئيسية. أداة الشهر ليس لديه إعداد — تتناسب شبكته دائمًا نفسه للمساحة التي تمنحها إيّاه.</string>
<string name="settings_agenda_widget_range_hint">كم مدى يعرض جدول أداة الشاشة الرئيسية الأحداث.</string>
<string name="settings_agenda_range_hint">كم مدى يعرض شاشة الجدول الأحداث.</string>
<string name="settings_agenda_widget_range_hint">كم مدى يُدرج جدول أداة الشاشة الرئيسية الأحداث.</string>
<string name="settings_agenda_range_hint">كم مدى يُدرج شاشة الجدول الأحداث.</string>
<string name="app_name">Calendula</string>
<string name="font_atkinson_hyperlegible">Atkinson Hyperlegible</string>
<string name="settings_special_dates_show_year">إظهار السنة</string>
@@ -696,13 +693,46 @@
<string name="font_lora">Lora</string>
<string name="font_jetbrains_mono">JetBrains Mono</string>
<string name="onboarding_backup_benefit_folder_title">مجلد تختاره</string>
<string name="import_warning_timezone">منطقة زمنية غير معروفة ترجع إلى الخاصة بجهازك.</string>
<string name="settings_calendar_reminders_managed_hint">تعيين في تواريخ جهات الاتصال الخاصة</string>
<string name="settings_special_dates_disable_all_message">يؤدي هذا إلى حذف تقويمات تواريخ جهات الاتصال وأحداثها. سيتم فقدان أي تذكيرات أو ملاحظات أضفتها إليها.</string>
<string name="import_warning_timezone">تمت إعادة منطقة زمنية غير معروفة إلى الخاصّة بجهازك.</string>
<string name="settings_calendar_reminders_managed_hint">تعيين في التواريخ الخاصة لجهات الاتصال</string>
<string name="settings_special_dates_disable_all_message">يؤدي هذا لحذف تقويمات تواريخ جهات الاتصال وأحداثها. سيتم فقدان أي تذكيرات أو ملاحظات أضفتها إليها.</string>
<string name="settings_special_dates_type_anniversary">الذكرات السنوية</string>
<string name="settings_special_dates_template_hint">استخدم {name} لجهة الاتصال و{year} للسنة (سنة الميلاد، أو سنة بدء الذكرى السنوية؛ مخفية عندما تكون غير معروفة).</string>
<string name="settings_special_dates_template">صيغة العنوان</string>
<string name="settings_calendar_reminders_hint">تجاوز الافتراضي لكل تقويم — بشكل منفصل للمحدد بوقت وأحداث طوال اليوم. يمكن لتقويم الاحتفاظ بالافتراضي، إسقاطه أو تعيين خاصّته.</string>
<string name="event_move_occurrence_only">سيؤدي نقل السلسلة بأكملها لتغيير الأيام التي تقع فيها، لذلك يمكن نقل هذا الحدث فقط.</string>
<string name="agenda_empty_title">أنت على اطلاع</string>
<string name="event_move_occurrence_only">سيؤدي نقل السلسلة بأكملها لتغيير أيٍّ الأيام التي تقع فيها، لذلك يمكن نقل هذا الحدث فقط.</string>
<string name="agenda_empty_title">أنت بالكل على آخر اطلاع</string>
<string name="reminder_after">%1$s بعد</string>
<string name="import_done_failed_label">لم تتم الإضافة</string>
<string name="import_done_failed_note">تعذّر إضافة بعض الأحداث وتم استبعادها.</string>
<string name="import_done_stopped_title">تم إيقاف الاستيراد</string>
<string name="import_warning_tasks">تمت إضافة المهام في هذا الملف كأحداث.</string>
<string name="import_warning_recurrence_repaired">تم إصلاح قاعدة تكرار معطّلة.</string>
<plurals name="import_done_stopped">
<item quantity="zero">التقويم توقف عن قبول الأحداث في منتصف العملية. لم تتم إضافة (%d) لا حدث من الملف مطلقًا.</item>
<item quantity="one">التقويم توقف عن قبول الأحداث في منتصف العملية. لم تتم إضافة %d حدث من الملف مطلقًا.</item>
<item quantity="two">التقويم توقف عن قبول الأحداث في منتصف العملية. لم تتم إضافة %d حدثان من الملف مطلقًا.</item>
<item quantity="few">التقويم توقف عن قبول الأحداث في منتصف العملية. لم تتم إضافة %d أحداث من الملف مطلقًا.</item>
<item quantity="many">التقويم توقف عن قبول الأحداث في منتصف العملية. لم تتم إضافة %d حدث من الملف مطلقًا.</item>
<item quantity="other">التقويم توقف عن قبول الأحداث في منتصف العملية. لم تتم إضافة %d حدث من الملف مطلقًا.</item>
</plurals>
<plurals name="import_done_failed">
<item quantity="zero">تعذّر إضافة (%d) لا أحداث.</item>
<item quantity="one">تعذّر إضافة %d حدث.</item>
<item quantity="two">تعذّر إضافة %d حدثان.</item>
<item quantity="few">تعذّر إضافة %d أحداث.</item>
<item quantity="many">تعذّر إضافة %d حدث.</item>
<item quantity="other">تعذّر إضافة %d حدث.</item>
</plurals>
<string name="state_failure_all_hidden">تم تعطيل جميع تقويماتك.</string>
<string name="state_failure_all_hidden_action">إدارة التقويمات</string>
<string name="field_copy_action">نسخ</string>
<string name="field_copied">تم النسخ إلى الحافظة</string>
<string name="field_copy_failed">تعذّر نسخ ذلك</string>
<string name="event_detail_title">العنوان</string>
<string name="settings_licences">تراخيص مفتوحة المصدر</string>
<string name="settings_licences_subtitle">المشاريع التي بنيت ‌‌Calendula عليها</string>
<string name="licences_title">تراخيص مفتوحة المصدر</string>
<string name="licences_intro">يتضمن Calendula العمل أدناه. اضغط على أي إدخال للحصول على شفرة المصدر الخاصة به.</string>
<string name="licences_footer">يتم تضمين كل مشروع هنا دون تعديل، بموجب الترخيص الموضح.</string>
</resources>
+80
View File
@@ -584,4 +584,84 @@
<string name="calendars_auto_backup_hint">Пэрыядычны экспарт лякальных календароў у каталёг у выглядзе файла .ics.</string>
<string name="calendars_auto_backup_folder">Каталёг рэзэрвовага капіяваньня</string>
<string name="calendars_auto_backup_folder_unset">Націсьніце, каб выбраць каталёг</string>
<string name="calendars_auto_backup_interval">Інтэрвал</string>
<string name="calendars_auto_backup_every">Кожн. %1$s</string>
<string name="calendars_auto_backup_interval_min">Мінімум 30 хв.</string>
<string name="calendars_auto_backup_status_never">Аўтаматычнае рэзэрвовае капіяваньне ня ўключана</string>
<string name="calendars_auto_backup_status_ok">Апошняе рэзэрвовае капіяваньне: %1$s</string>
<string name="calendars_auto_backup_status_failed">Апошняе няўдалае рэзэрвовае капіяваньне: %1$s</string>
<string name="backup_channel_name">Рэзэрвовае капіяваньне</string>
<string name="backup_channel_description">Папярэджвае аб шматразовых няўдачах аўтаматычнага рэзэрвовага капіяваньня.</string>
<string name="backup_failed_title">Памылка аўтаматычнага рэзэрвовага капіяваньня</string>
<string name="backup_failed_text">Calendula не ўдалося зрабіць файл рэзэрвовай копіі. Праверце каталёг рэзэрвовага капіяваньня ў наладах.</string>
<string name="calendars_backup_failed">Не атрымалася экспартаваць рэзэрвовую копію.</string>
<plurals name="calendars_backup_done">
<item quantity="one">Экспартавана %d падзея.</item>
<item quantity="few">Экспартавана падзеяў: %d.</item>
<item quantity="many">Экспартавана падзеяў: %d.</item>
<item quantity="other">Экспартавана падзеяў: %d.</item>
</plurals>
<string name="import_title">Імпартаваць падзеі</string>
<string name="import_target_header">Дадаць у каляндар</string>
<string name="import_empty">У гэтым файле падзеі ня знойдзены.</string>
<string name="import_failed">Не атрымалася прачытаць гэты файл.</string>
<string name="import_no_calendar">Няма календара з дазволам на запіс, у які можна імпартаваць зьвесткі. Спачатку стварэце лякальны каляндар.</string>
<string name="import_done_title">Імпарт завершаны</string>
<string name="import_done_dedup_note">Падзеі, якія ўжо ёсьць у календары, былі прамінутыя.</string>
<string name="import_done_added_label">Дадана</string>
<string name="import_done_skipped_label">Дублікаты</string>
<string name="import_close">Закрыць</string>
<string name="import_warning_recurrence">Былі прамінутыя некаторыя зьмененыя паўторныя падзеі.</string>
<string name="import_warning_no_start">Падзея бяз часу пачатку была прамінутая.</string>
<string name="import_warning_attendees">Сьпісы наведвальнікаў не былі імпартаваныя.</string>
<string name="import_warning_timezone">Замест невядомага часавага поясу ўжыты сыстэмны для вашай прылады.</string>
<string name="import_button">Імпарт</string>
<plurals name="import_title_count">
<item quantity="one">Імпартуецца %d падзея</item>
<item quantity="few">Імпартуецца падзеяў: %d</item>
<item quantity="many">Імпартуецца падзеяў: %d</item>
<item quantity="other">Імпартуецца падзеяў: %d</item>
</plurals>
<plurals name="import_event_count">
<item quantity="one">%d падзея ў гэтым файле.</item>
<item quantity="few">Падзеяў у гэтым файле: %d.</item>
<item quantity="many">Падзеяў у гэтым файле: %d.</item>
<item quantity="other">Падзеяў у гэтым файле: %d.</item>
</plurals>
<plurals name="import_action">
<item quantity="one">Імпарт %d падзеі</item>
<item quantity="few">Імпарт падзеяў: %d</item>
<item quantity="many">Імпарт падзеяў: %d</item>
<item quantity="other">Імпарт падзеяў: %d</item>
</plurals>
<plurals name="import_done_imported">
<item quantity="one">Імпартавана %d падзея.</item>
<item quantity="few">Імпартавана падзеяў: %d.</item>
<item quantity="many">Імпартавана падзеяў: %d.</item>
<item quantity="other">Імпартавана падзеяў: %d.</item>
</plurals>
<plurals name="import_done_skipped">
<item quantity="one">Прамінута %d падзея (ужо ёсьць у гэтым календары).</item>
<item quantity="few">Прамінута падзеяў: %d (ужо ёсьць у гэтым календары).</item>
<item quantity="many">Прамінута падзеяў: %d (ужо ёсьць у гэтым календары).</item>
<item quantity="other">Прамінута падзеяў: %d (ужо ёсьць у гэтым календары).</item>
</plurals>
<string name="shortcut_new_event_short">Новая падзея</string>
<string name="shortcut_new_event_long">Стварыць новую падзею</string>
<string name="qs_tile_new_event_label">Новая падзея</string>
<string name="settings_qs_tile">Дадаць плітку хуткіх наладаў</string>
<string name="settings_qs_tile_hint">Дадаць плітку «Новая падзея» на панэль хуткіх наладаў.</string>
<string name="crash_dialog_title">Крах %1$s</string>
<string name="crash_dialog_message">Апошнім разам %1$s нечакана закрылася. Вы можаце дапамагчы выправіць гэта, адправіўшы справаздачу аб праблеме. Яна застанецца на вашай прыладзе, пакуль вы не вырашыце падзяліцца ёю, і ня ўтрымлівае асабістых даных або зьмесціва календара — толькі тэхнічныя падрабязнасьці, паданыя ніжэй.</string>
<string name="crash_dialog_report">Справаздача</string>
<string name="crash_dialog_dismiss">Ня зараз</string>
<string name="crash_report_clip_label">Справаздача аб краху %1$s</string>
<string name="crash_report_copied">Справаздача скапіявана ў буфэр абмену</string>
<string name="crash_report_open_failed">Не атрымалася адкрыць сыстэму адсочваньня праблемаў. Справаздача знаходзіцца ў буфэры абмену.</string>
<string name="special_dates_calendar_birthday">Дні нараджэньня</string>
<string name="special_dates_calendar_anniversary">Юбілейныя даты</string>
<string name="special_dates_calendar_custom">Асаблівыя даты</string>
<string name="special_dates_default_title_birthday">Дзень нараджэньня {name} ({year})</string>
<string name="special_dates_default_title_anniversary">Юбілейная дата {name} ({year})</string>
<string name="special_dates_default_title_custom">{name}</string>
</resources>
+174 -21
View File
@@ -45,7 +45,7 @@
<string name="event_detail_edit">Upravit</string>
<string name="event_detail_delete">Odstranit</string>
<string name="event_detail_share">Sdílet</string>
<string name="event_detail_duplicate">Kopírovat</string>
<string name="event_detail_duplicate">Duplikovat</string>
<string name="event_share_chooser_title">Sdílet událost</string>
<string name="event_share_failed">Tuto událost nelze sdílet.</string>
<string name="event_delete_title">Odstranit událost?</string>
@@ -73,7 +73,7 @@
<string name="event_edit_close">Zavřít</string>
<string name="event_edit_save">Uložit</string>
<string name="event_edit_title_hint">Přidat název</string>
<string name="event_edit_managed_hint">Spravováno aplikací „%1$s“ — název, datum a opakování je synchronizováno z vašich kontaktů. Upomínky, polohu a poznámky si můžete upravit sami.</string>
<string name="event_edit_managed_hint">Spravováno aplikací „%1$s“ — název, datum a opakování je synchronizováno z vašich kontaktů. Připomínky, polohu a poznámky si můžete upravit sami.</string>
<string name="event_edit_starts">Začátek</string>
<string name="event_edit_ends">Konec</string>
<string name="event_edit_error_end_before_start">Končí dříve, než začíná</string>
@@ -82,8 +82,8 @@
<string name="event_edit_write_denied">Calendula pro vytváření událostí vyžaduje oprávnění k zápisu</string>
<string name="event_edit_more_fields">další pole</string>
<string name="event_edit_add">Přidat</string>
<string name="event_edit_add_reminder">Přidat upomínku</string>
<string name="event_edit_remove_reminder">Vymazat upomínku</string>
<string name="event_edit_add_reminder">Přidat připomínku</string>
<string name="event_edit_remove_reminder">Vymazat připomínku</string>
<string name="event_edit_attendees">Hosté</string>
<string name="event_edit_add_guest">Přidat hosta</string>
<string name="event_edit_add_guest_hint">Přidat hosta e-mailem…</string>
@@ -123,13 +123,13 @@
<string name="event_edit_conflict_discard_hint">Událost zůstává beze změny</string>
<string name="event_edit_gone_title">Událost byla odstraněna</string>
<string name="event_edit_gone_body">Během úpravy došlo k odstranění události, například pomocí jiného zařízení. Vaše změny již nelze uložit.</string>
<string name="import_reminder_prompt_title">Chcete použít výchozí upomínku?</string>
<string name="import_reminder_prompt_body_none">Tato událost byla importována bez nastavené upomínky.</string>
<string name="import_reminder_prompt_title">Chcete použít výchozí připomínku?</string>
<string name="import_reminder_prompt_body_none">Tato událost byla importována bez nastavené připomínky.</string>
<plurals name="import_reminder_prompt_body_existing">
<item quantity="one">Tato událost byla importována s %1$d upomínkou.</item>
<item quantity="few">Tato událost byla importována s %1$d upomínkami.</item>
<item quantity="many">Tato událost byla importována s %1$d upomínkami.</item>
<item quantity="other">Tato událost byla importována s %1$d upomínkami.</item>
<item quantity="one">Tato událost byla importována s %1$d připomínkou.</item>
<item quantity="few">Tato událost byla importována s %1$d připomínkami.</item>
<item quantity="many">Tato událost byla importována s %1$d připomínkami.</item>
<item quantity="other">Tato událost byla importována s %1$d připomínkami.</item>
</plurals>
<string name="import_reminder_prompt_apply">Nastavit výchozí</string>
<string name="import_reminder_prompt_keep">Nechat beze změny</string>
@@ -155,7 +155,7 @@
<string name="event_detail_all_day">Celý den</string>
<string name="event_detail_calendar">Kalendář</string>
<string name="event_detail_calendar_unknown">Neznámý kalendář</string>
<string name="event_detail_location">Umístění</string>
<string name="event_detail_location">Místo</string>
<string name="event_detail_description">Popis</string>
<string name="event_detail_attendees">Účastníci</string>
<string name="event_detail_recurrence">Opakování</string>
@@ -177,7 +177,7 @@
<string name="event_attendee_tentative">Předběžné</string>
<string name="event_attendee_needs_action">Bez odezvy</string>
<string name="event_attendee_unknown"></string>
<string name="event_detail_reminders">Upomínky</string>
<string name="event_detail_reminders">Připomínky</string>
<string name="event_detail_timezone">Časové pásmo</string>
<string name="event_status_tentative">Přeběžné</string>
<string name="event_status_cancelled">Zrušeno</string>
@@ -193,7 +193,7 @@
<string name="event_attendee_resource">Zdroj</string>
<string name="event_detail_self_response">Vaše odpověď: %1$s</string>
<string name="reminder_at_time">V době konání události</string>
<string name="reminder_default">Výchozí upomínka</string>
<string name="reminder_default">Výchozí připomínka</string>
<plurals name="reminder_minutes">
<item quantity="one">%d minutu předtím</item>
<item quantity="few">%d minuty předtím</item>
@@ -261,17 +261,17 @@
<string name="onboarding_done_title">Vše je připraveno</string>
<string name="onboarding_done_body">Vaše kalendáře jsou připraveny. Veškeré volby lze později změnit v nastavení.</string>
<string name="onboarding_done_button">Otevřít můj kalendář</string>
<string name="reminder_channel_name">Upomínky událostí</string>
<string name="reminder_channel_description">Oznámení v časech upomínek vašich událostí</string>
<string name="reminder_channel_name">Připomínky událostí</string>
<string name="reminder_channel_description">Oznámení v časech připomínek vašich událostí</string>
<string name="reminder_onboarding_title">Ať vám neunikne žádná událost</string>
<string name="reminder_onboarding_body">Android sám o sobě nezobrazuje upomínky událostí to musí zajistit aplikace kalendáře. Nechte tuto práci na Calendule.</string>
<string name="reminder_benefit_delivery_title">Upomínky, doručené</string>
<string name="reminder_benefit_delivery_body">Upomínky k vašim událostem vám přijdou v danou dobu jako oznámení.</string>
<string name="reminder_onboarding_body">Android sám o sobě nezobrazuje připomínky událostí to musí zajistit aplikace kalendáře. Nechte tuto práci na Calendule.</string>
<string name="reminder_benefit_delivery_title">Připomínky, doručené</string>
<string name="reminder_benefit_delivery_body">Připomínky k vašim událostem vám přijdou v danou dobu jako oznámení.</string>
<string name="reminder_benefit_duplicates_title">Používáte ještě nějakou jinou aplikaci s kalendářem?</string>
<string name="reminder_benefit_duplicates_body">Pokud i jiná aplikace odesílá upomínky, uvidíte je dvakrát — v jedné z aplikací je musíte vypnout.</string>
<string name="reminder_benefit_duplicates_body">Pokud i jiná aplikace odesílá připomínky, uvidíte je dvakrát — v jedné z aplikací je musíte vypnout.</string>
<string name="reminder_benefit_reversible_title">Lze kdykoliv změnit</string>
<string name="reminder_benefit_reversible_body">Tento přepínač naleznete v Nastavení, v části Oznámení.</string>
<string name="reminder_onboarding_enable_button">Zapnout upomínky</string>
<string name="reminder_onboarding_enable_button">Zapnout připomínky</string>
<string name="reminder_onboarding_skip_button">Později</string>
<string name="reminder_action_snooze">Odložit</string>
<string name="reminder_action_dismiss">Zrušit</string>
@@ -280,7 +280,7 @@
<string name="view_month">Měsíc</string>
<string name="view_week">Týden</string>
<string name="view_day">Den</string>
<string name="view_agenda">Program</string>
<string name="view_agenda">Agenda</string>
<string name="view_section">Zobrazení</string>
<string name="drawer_jump_to_date">Přejít na datum</string>
<string name="agenda_today_action">Dnes</string>
@@ -332,4 +332,157 @@
<string name="widget_next_month">Následující měsíc</string>
<string name="widget_today">Dnes</string>
<string name="filter_title">Kalendáře</string>
<string name="reminder_after">%1$s po</string>
<string name="settings_title">Nastavení</string>
<string name="settings_back">Zpět</string>
<string name="back">Zpět</string>
<string name="settings_section_appearance">Vzhled</string>
<string name="settings_theme">Motiv</string>
<string name="settings_theme_system">Systém</string>
<string name="settings_theme_light">Světlý</string>
<string name="settings_theme_dark">Tmavý</string>
<string name="settings_theme_hint">Světlý nebo tmavý motiv aplikace. Volba se projeví okamžitě.</string>
<string name="settings_theme_system_summary">Nyní je nastaven %1$s</string>
<string name="settings_default_view">Výchozí zobrazení</string>
<string name="settings_dynamic_color">Dynamické barvy</string>
<string name="settings_dynamic_color_unavailable">Je zapotřepí Android 12 či novější</string>
<string name="settings_soften_colors">Sladit barvy kalendáře</string>
<string name="settings_soften_colors_summary">Zachovat odstín každého kalendáře, ale vyrovnat jeho jas, aby každá událost zůstala čitelná a barvy k sobě ladily. Vypnutím této funkce se zobrazí původní barvy zdrojového kalendáře.</string>
<string name="settings_font_headings">Písmo nadpisů</string>
<string name="settings_font_body">Písmo těla textu</string>
<string name="settings_font_system">Výchozí nastavení systému</string>
<string name="font_atkinson_hyperlegible">Atkinson Hyperlegible</string>
<string name="font_lora">Lora</string>
<string name="font_jetbrains_mono">JetBrains Mono</string>
<string name="settings_font_choose_file">Vybrat soubor…</string>
<string name="settings_font_custom_selected">Vlastní písmo</string>
<string name="settings_font_import_failed">Tento soubor se nepodařilo načíst jako písmo</string>
<string name="settings_font_specimen_heading">Čtvrtek, 14. května</string>
<string name="settings_font_specimen_body">V 10:00 proběhne porada týmu, poté oběd s Robinem v kavárně na náměstí.</string>
<string name="settings_week_start">Týden začíná dnem</string>
<string name="settings_week_start_auto">Automaticky</string>
<string name="settings_week_start_auto_summary">Nyní %1$s</string>
<string name="settings_week_numbers">Čísla týdnů</string>
<string name="settings_week_numbers_summary">Zobrazit čísla týdnů kalendáře v měsíčním zobrazení</string>
<string name="settings_today_toolbar">Tlačítko „Dnes“ na panelu nástrojů</string>
<string name="settings_today_toolbar_summary">Zobrazit na panelu nástrojů tlačítko „Přejít na dnešek“ namísto plovoucího tlačítka</string>
<string name="settings_app_name">Název aplikace</string>
<string name="settings_app_name_summary">Zobrazí aplikaci Calendula jako „Kalendář“ ve vašem spouštěči. Změní se pouze název ve spouštěči; ikona se po přepnutí může přesunout na jiné místo.</string>
<string name="settings_time_format">Formát času</string>
<string name="settings_time_format_auto">Automaticky</string>
<string name="settings_time_format_12h">12hodinový (2:00 PM)</string>
<string name="settings_time_format_24h">24hodinový (14:00)</string>
<string name="settings_time_format_auto_summary">Podle systému: %1$s</string>
<string name="settings_hour_lines">Hodinová mřížka</string>
<string name="settings_hour_lines_summary">Zobrazit oddělovací čáru u každé hodiny v dané buňce v týdenním a denním zobrazení</string>
<string name="settings_timeline_scale">Výška hodin</string>
<string name="settings_timeline_scale_hint">Kolik vertikálního prostoru zabírá jedna hodina v týdenním a denním zobrazení. Toto nastavení platí pro obě zobrazení. Výšku časové osy můžete v rámci daného rozmezí nastavit pomocí gesta přiblížení dvěma prsty.</string>
<string name="timeline_scale_fit_day">Přizpůsobit se dennímu zobrazení</string>
<string name="timeline_scale_fit_day_summary">Všech 24 hodin na jedné obrazovce, bez nutnosti posouvání</string>
<string name="timeline_scale_compact">Kompaktní</string>
<string name="timeline_scale_compact_summary">Více hodin na obrazovce, menší bloky</string>
<string name="timeline_scale_regular">Normální</string>
<string name="timeline_scale_regular_summary">Standardní rozestup</string>
<string name="timeline_scale_comfortable">Pohodlná</string>
<string name="timeline_scale_comfortable_summary">Prostornější bloky, více posouvání</string>
<string name="timeline_scale_custom">Vlastní</string>
<string name="timeline_scale_custom_summary">Výška, na kterou jste časovou osu nastavili gestem</string>
<string name="settings_dim_completed">Ztmavit dokončené události</string>
<string name="settings_dim_completed_summary">Ztmavit dokončené události v měsíčním a týdenním zobrazení</string>
<string name="settings_drag_to_reschedule">Přetažením změňte termín</string>
<string name="settings_drag_to_reschedule_summary">Přesuňte událost přetažením na jiný den nebo čas</string>
<string name="settings_past_events">Uplynulé události</string>
<string name="settings_past_events_show">Zobrazit</string>
<string name="settings_past_events_dim">Ztmavit</string>
<string name="settings_past_events_hide">Skrýt</string>
<string name="settings_past_events_sample_morning">Přehled týmu</string>
<string name="settings_past_events_sample_midday">Oběd s Robinem</string>
<string name="settings_past_events_sample_evening">Zkouška sboru</string>
<string name="settings_agenda_header">Agenda</string>
<string name="settings_agenda_range">Rozsah agendy</string>
<string name="settings_agenda_range_hint">Jak daleko do budoucna zobrazuje obrazovka „Agenda“ události.</string>
<string name="settings_agenda_widget_range">Rozsah widgetu agendy</string>
<string name="settings_agenda_widget_range_hint">Jak daleko dopředu widget agendy na domovské obrazovce zobrazuje události.</string>
<string name="settings_widget_size">Velikost widgetu agendy</string>
<string name="settings_widget_size_hint">Velikost textu zobrazeného ve widgetu „Agenda“ na domovské obrazovce. Widget „Měsíc“ nemá žádné nastavení jeho mřížka se vždy přizpůsobí prostoru, který mu přidělíte.</string>
<string name="settings_widget_size_small">Malý</string>
<string name="settings_widget_size_medium">Střední</string>
<string name="settings_widget_size_large">Velký</string>
<string name="settings_widget_size_extra_large">Největší</string>
<string name="settings_widget_size_summary">Text události%1$d</string>
<string name="settings_agenda_show_today">Vždy zobrazovat dnešek</string>
<string name="settings_agenda_show_today_hint">Ponechat dnešní den na prvním místě agendy a jejího widgetu, třebaže již nezbývá žádná nadcházející událost.</string>
<string name="state_failure_all_hidden">Všechny vaše kalendáře jsou vypnuté.</string>
<string name="state_failure_all_hidden_action">Správa kalendářů</string>
<string name="field_copy_action">Kopírovat</string>
<string name="field_copied">Zkopírováno do schránky</string>
<string name="field_copy_failed">Toto se nepodařilo zkopírovat</string>
<string name="event_detail_title">Název</string>
<string name="agenda_range_day">Dnes</string>
<string name="agenda_range_this_week">Tento týden</string>
<string name="agenda_range_this_month">Tento měsíc</string>
<string name="agenda_range_week">Následujících 7 dní</string>
<string name="agenda_range_month">Následujících 30 dní</string>
<string name="agenda_range_custom">Vlastní…</string>
<string name="agenda_range_custom_hint">Dny</string>
<string name="agenda_range_override_hint">Pouze dočasně při opětovném spuštění aplikace Calendula se nastavení vrátí k uloženému rozsahu.</string>
<string name="settings_agenda_range_bar">Lišta s rozmezím</string>
<string name="settings_agenda_range_bar_hint">V horní části agendy se zobrazí lišta s rozsahem dat a tlačítkem pro změnu rozsahu dané relace</string>
<string name="agenda_range_showing_label">Zobrazit všechny nadcházející události pro</string>
<plurals name="agenda_range_days">
<item quantity="one">%dden</item>
<item quantity="few">%ddny</item>
<item quantity="many">%ddnů</item>
<item quantity="other">%ddnů</item>
</plurals>
<string name="settings_section_views">Pohledy</string>
<string name="settings_month_header">Měsíční zobrazení</string>
<string name="settings_month_view_style">Styl měsíčního zobrazení</string>
<string name="month_style_paged">Stránky</string>
<string name="month_style_paged_summary">Na obrazovce se zobrazuje jeden měsíc. Přejetím prstem doleva nebo doprava můžete změnit měsíc.</string>
<string name="month_style_continuous">Posouvání měsíců</string>
<string name="month_style_continuous_summary">Každý měsíc je zobrazen pod vlastním nadpisem, od následujícího je oddělen malou mezerou.</string>
<string name="month_style_dense">Nepřerušené týdny</string>
<string name="month_style_dense_summary">Týdny plynule navazují na sebe, jeden měsíc přechází do druhého, aniž by mezi nimi byla nějaká mezera.</string>
<string name="month_style_split_summary">Kompaktní mřížka označuje dny, ve kterých se konají události, a den, na který klepnete, je zobrazen pod ní.</string>
<string name="month_style_split">Rozdělení</string>
<string name="month_split_no_events">Není nic naplánováno</string>
<string name="month_split_expand">Zobrazit celý měsíc</string>
<string name="month_split_collapse">Zobrazit události dne</string>
<string name="settings_quick_switch_header">Tlačítko pro rychlé přepnutí</string>
<string name="settings_quick_switch_hint">Vyberte, která zobrazení bude přepínat tlačítko v pravém horním rohu, a přetažením je seřaďte. Pokud jsou zapnutá méně než dvě zobrazení, tlačítko se skryje. Vypnutá zobrazení zůstanou přístupná z navigačního menu.</string>
<string name="settings_drawer_order_header">Navigační menu</string>
<string name="settings_drawer_order_hint">Přetažením změníte pořadí zobrazení uvedených v navigačním menu.</string>
<string name="reorder_drag_handle">Přetažením změňte pořadí</string>
<string name="settings_section_event_form">Formulář nové události</string>
<string name="settings_form_fields_hint">Pole zobrazená ve výchozím nastavení — vše ostatní se zobrazí kliknutím na „Další pole“</string>
<string name="settings_autofocus_title">Zaměření názvu při vytváření nové události</string>
<string name="settings_autofocus_title_hint">Při vytváření nové události se kurzor umístí do pole názvu, otevře se klávesnice.</string>
<string name="settings_event_duration">Výchozí doba trvání</string>
<string name="settings_event_duration_hint">Jak dlouho nová událost trvá, dokud nezměníte čas jejího ukončení. Celodenní události tím nejsou ovlivněny.</string>
<string name="settings_calendar_durations_title">Doba trvání podle kalendáře</string>
<string name="settings_calendar_durations_hint">Nastavte kalendáři vlastní výchozí délku například 8 hodin pro pracovní směny.</string>
<string name="settings_calendar_duration_inherits">Výchozí (%1$s)</string>
<string name="settings_calendar_duration_use_default">Použít výchozí dobu trvání (%1$s)</string>
<string name="settings_color_unsupported">Povolit barvy u nepodporovaných kalendářů</string>
<string name="settings_color_unsupported_hint">Jisté kalendáře (např. některé typu CalDAV) neposkytují vlastní definici barev; barva události tak může být při příští synchronizaci ztracena nebo přepsána. Jde o omezení daných kalendářů, nikoli o problém Calenduly.</string>
<string name="settings_section_notifications">Oznámení</string>
<string name="settings_reminders">Připomínky událostí</string>
<string name="settings_reminders_hint">Vidíte připomínky dvakrát? Zobrazuje je i jiná aplikace kalendáře v jedné z nich je vypněte.</string>
<string name="settings_default_reminder">Výchozí připomínka</string>
<string name="settings_default_reminder_allday">Celodenní události</string>
<string name="settings_allday_reminder_time">Čas celodenní připomínky</string>
<string name="settings_allday_reminder_time_hint">Připomínky na celodenní události se spouštějí v %1$s</string>
<string name="settings_allday_reminder_fires_at">Upozorní v %1$s</string>
<string name="reminder_none">Žádná</string>
<string name="reminder_use_default">Použít výchozí připomínku</string>
<string name="reminder_custom_amount">Množství</string>
<string name="reminder_custom_set">Nastavit</string>
<string name="settings_calendar_reminders_title">Připomínky pro jednotlivé kalendáře</string>
<string name="settings_calendar_reminders_hint">Přepíše výchozí nastavení pro jednotlivé kalendáře zvlášť pro události s konkrétním časem a pro celodenní události. Kalendář může zachovat výchozí nastavení, zrušit jej nebo nastavit vlastní.</string>
<string name="settings_calendar_reminder_inherits">Výchozí (%1$s)</string>
<string name="settings_reliable_delivery_hint">Android může kvůli úspoře baterie odložit připomínky. Udělte aplikaci Calendula výjimku, aby se zobrazovaly bez prodlení.</string>
<string name="settings_reliable_delivery_exempt">Výloučení z optimalizace baterie připomínky chodí bez prodlení.</string>
<string name="settings_notifications_subtitle">Připomínky a doručení</string>
<string name="settings_special_dates_reminders">Připomínky</string>
</resources>
-3
View File
@@ -382,12 +382,9 @@
<string name="crash_dialog_message">%1$s wurde beim letzten Mal unerwartet beendet. Du kannst bei der Behebung helfen, indem du diesen Bericht als Issue sendest. Er bleibt auf deinem Gerät, bis du ihn teilst, und enthält keine persönlichen Daten oder Kalenderinhalte — nur die technischen Angaben unten.</string>
<string name="crash_dialog_report">Melden</string>
<string name="crash_dialog_dismiss">Nicht jetzt</string>
<string name="crash_report_issue_title">Absturzbericht</string>
<string name="crash_report_clip_label">%1$s-Absturzbericht</string>
<string name="crash_report_copied">Bericht in die Zwischenablage kopiert</string>
<string name="crash_report_open_failed">Der Issue-Tracker konnte nicht geöffnet werden. Der Bericht ist in deiner Zwischenablage.</string>
<string name="crash_report_body_template">Danke, dass du einen Absturz in %1$s meldest. Bitte ergänze, was du gerade getan hast, und sende dann ab.\n\n### Was ist passiert\n\n\n### Absturzbericht\n%2$s\n</string>
<string name="crash_report_body_paste">_(Der Bericht war zu lang für diesen Link — füge ihn aus deiner Zwischenablage hier ein.)_</string>
<string name="event_edit_managed_hint">Verwaltet durch “%1$s” — der Titel, das Datum und Wiederholungen werden synchron mit deinen Kontakten gehalten. Erinnerungen, Ort und Beschreibung kannst du frei bearbeiten.</string>
<plurals name="duration_days">
<item quantity="one">%d Tag</item>
-3
View File
@@ -405,12 +405,9 @@
<string name="crash_dialog_message">%1$s se cerro de forma inesperada la ultima vez. Puedes ayudar a solucionarlo enviando un reporte del problema. Este permanece en tu dispositivo hasta que decidas enviarlo, y no contiene información personal o contenido de tu calendario — solo los detalles técnicos de mas abajo.</string>
<string name="crash_dialog_report">Reportar</string>
<string name="crash_dialog_dismiss">No por ahora</string>
<string name="crash_report_issue_title">Reporte de error</string>
<string name="crash_report_clip_label">Reporte de error de %1$s</string>
<string name="crash_report_copied">Reporte copiado a tu porta papeles</string>
<string name="crash_report_open_failed">No se pudo abrir el sistema de seguimiento de errores. El reporte es en tu portapapeles.</string>
<string name="crash_report_body_template">Gracias por reportar un error en %1$s. Por favor añade todo lo que recuerdas sobre lo que estabas haciendo y luego publicalo.\n\n### que sucedió\n\n\n### reporte de error\n%2$s\n</string>
<string name="crash_report_body_paste">_(el reporte es demasiado largo para este link — pegalo aquí desde su portapeles.)_</string>
<string name="event_attendee_resource">Recurso</string>
<string name="settings_section_about">Acerca de</string>
<string name="recurrence_with_count">%1$s, %2$d veces</string>
+1 -3
View File
@@ -323,6 +323,7 @@
<plurals name="agenda_range_days">
<item quantity="one">%d jour</item>
<item quantity="many">%d jours</item>
<item quantity="other">%d jours</item>
</plurals>
<string name="settings_section_views">Vues</string>
<string name="settings_quick_switch_header">Bouton dinterrupteur rapide</string>
@@ -486,12 +487,9 @@
<string name="crash_dialog_message">%1$s a été fermé de manière inattendue la dernière fois. Vous pouvez aider à le corriger en envoyant ce rapport en tant que problème. Il reste sur votre appareil jusqu’à ce que vous choisissiez de le partager, et ninclut aucune donnée personnelle ni contenu de calendrier — seuls les détails techniques ci-dessous.</string>
<string name="crash_dialog_report">rapport</string>
<string name="crash_dialog_dismiss">pas maintenant</string>
<string name="crash_report_issue_title">rapport de plantage</string>
<string name="crash_report_clip_label">%1$s rapport de plantage</string>
<string name="crash_report_copied">Rapport copié dans votre presse-papiers</string>
<string name="crash_report_open_failed">Impossible douvrir le suivi des problèmes. Le rapport se trouve dans votre presse-papiers.</string>
<string name="crash_report_body_template">Merci davoir signalé un plantage dans %1$s. Veuillez ajouter tout ce dont vous vous souvenez sur ce que vous faisiez, puis soumettez-le.\n\n### Que sest-il passé\n\n\n### Rapport de plantage\n%2$s\n</string>
<string name="crash_report_body_paste">_(Le rapport était trop long pour ce lien — collez-le depuis votre presse-papiers ici.)_</string>
<string name="special_dates_calendar_birthday">anniversaires</string>
<string name="special_dates_calendar_anniversary">Anniversaires</string>
<string name="special_dates_calendar_custom">dates spéciales</string>
+14 -3
View File
@@ -394,12 +394,9 @@
<string name="crash_dialog_message">%1$s si è chiuso inaspettatamente l\'ultima volta. Puoi contribuire allo sviluppo inviando questo report, che rimane sul tuo dispositivo finchè non scegli di inviarlo e non include informazioni personali o sui tuoi calendari: solo le informazioni tecniche qui sotto.</string>
<string name="crash_dialog_report">Report</string>
<string name="crash_dialog_dismiss">Non ora</string>
<string name="crash_report_issue_title">Crash report</string>
<string name="crash_report_clip_label">%1$s crash report</string>
<string name="crash_report_copied">Report copiato negli Appunti</string>
<string name="crash_report_open_failed">Impossibile aprire il gestore dei problemi. Il report è negli Appunti.</string>
<string name="crash_report_body_template">Grazie per segnalare un crash di %1$s. Per favore, aggiungi ogni informazione che ricordi in merito a quello che stavi facendo, quindi invia\n\n### Cosa è successo\n\n\n###Crash report\n%2$s\n</string>
<string name="crash_report_body_paste">_(Il report era troppo lungo per questo link - copialo qui dai tuoi Appunti.)_</string>
<string name="event_detail_recurrence">Ricorrenza</string>
<string name="event_detail_recurring">Evento ricorrente</string>
<string name="recurrence_on_days">%1$s da %2$s</string>
@@ -646,4 +643,18 @@
<string name="settings_default_view_hint">La vista di default all\'apertura dell\'app.</string>
<string name="settings_week_start_hint">Il giorno in cui inizia ogni settimana, in tutta l\'app e i suoi widget.</string>
<string name="settings_time_format_hint">Formato degli orari in tutta l\'app. Di default viene seguito il formato di sistema.</string>
<string name="state_failure_all_hidden_action">Gestisci calendari</string>
<string name="field_copy_action">Copia</string>
<string name="field_copied">Copiato negli appunti</string>
<string name="field_copy_failed">Impossibile copiarlo</string>
<string name="event_detail_title">Titolo</string>
<string name="reminder_after">%1$s dopo</string>
<string name="licences_title">Licenza open source</string>
<string name="licences_intro">Calendula include il codice riportato di seguito. Tocca una voce qualsiasi per visualizzarne il codice sorgente.</string>
<string name="licences_footer">Ogni progetto qui presente è incluso senza modifiche, secondo la licenza indicata.</string>
<string name="import_warning_tasks">Le attività contenute in questo file sono state aggiunte come eventi.</string>
<string name="import_warning_recurrence_repaired">È stata corretta una regola di ripetizione errata.</string>
<string name="import_done_failed_label">Non aggiunto</string>
<string name="import_done_failed_note">Alcuni eventi non possono essere aggiunti e sono stati esclusi.</string>
<string name="import_done_stopped_title">Importazione interrotta</string>
</resources>
-3
View File
@@ -495,12 +495,9 @@
<string name="crash_dialog_message">Aplikacja %1$s została nieoczekiwanie zamknięta przy ostatnim uruchomieniu. Możesz pomóc nam to naprawić, wysyłając zgłoszenie o błędzie. Pozostanie ono na Twoim urządzeniu, dopóki nie zdecydujesz się go udostępnić, i nie zawiera żadnych danych osobowych ani treści z kalendarza — jedynie poniższe szczegóły techniczne.</string>
<string name="crash_dialog_report">Zgłoś</string>
<string name="crash_dialog_dismiss">Nie teraz</string>
<string name="crash_report_issue_title">Raport o awarii</string>
<string name="crash_report_clip_label">Raport o awarii %1$s</string>
<string name="crash_report_copied">Raport skopiowany do schowka</string>
<string name="crash_report_open_failed">Nie udało się otworzyć systemu zgłoszeń. Raport znajduje się w Twoim schowku.</string>
<string name="crash_report_body_template">Dziękujemy za zgłoszenie awarii w aplikacji %1$s. Prosimy o dodanie wszelkich zapamiętanych szczegółów na temat wykonywanych czynności, a następnie przesłanie zgłoszenia.\n\n### Co się wydarzyło\n\n\n### Raport o awarii\n%2$s\n</string>
<string name="crash_report_body_paste">_(Raport był zbyt długi dla tego linku — wklej go tutaj ze schowka)._</string>
<string name="special_dates_calendar_custom">Szczególne daty</string>
<string name="special_dates_default_title_birthday">Urodziny {name} ({year})</string>
<string name="special_dates_default_title_anniversary">Rocznica {name} ({year})</string>
@@ -636,12 +636,9 @@
<string name="crash_dialog_message">%1$s fechou inesperadamente da última vez. Você pode ajudar a consertar enviando este reporte como um problema. Ele fica no seu dispositivo até que decida enviá-lo, e não inclui dados pessoais ou conteúdo de calendário — somente os detalhes técnicos abaixo.</string>
<string name="crash_dialog_report">Reportar</string>
<string name="crash_dialog_dismiss">Agora não</string>
<string name="crash_report_issue_title">Reportar quebra</string>
<string name="crash_report_clip_label">%1$s relatório de quebra</string>
<string name="crash_report_copied">Relatório copiado para a área de transferência</string>
<string name="crash_report_open_failed">Não foi possível abrir o tracker de problemas. O relatório está na área de transferência.</string>
<string name="crash_report_body_template">Obrigado por reportar uma quebra em %1$s. Por favor, escreva o que estava fazendo, depois envie. \n### O que aconteceu \n\n\n### Relatório de quebra \n%2$s\n</string>
<string name="crash_report_body_paste">_(O reporte era muito longo para este link — cole da área de transferência aqui.)_</string>
<string name="special_dates_calendar_birthday">Aniversários</string>
<string name="special_dates_calendar_anniversary">Aniversários de relacionamento</string>
<string name="special_dates_calendar_custom">Datas especiais</string>
+502
View File
@@ -6,4 +6,506 @@
<item>Days</item>
<item>Weeks</item>
</string-array>
<string name="app_name">Calendula</string>
<string name="app_tagline">Um calendário moderno.</string>
<string name="state_loading">A carregar…</string>
<string name="state_retry">Tentar novamente</string>
<string name="state_failure_unknown">Algo correu mal.</string>
<string name="state_failure_permission">O acesso ao calendário é necessário.</string>
<string name="state_failure_permission_action">Conceder acesso</string>
<string name="state_failure_no_calendars">Nenhum calendário configurado.</string>
<string name="state_failure_no_calendars_action">Abrir configurações do calendário do sistema</string>
<string name="state_failure_all_hidden">Todos os seus calendários estão desligados.</string>
<string name="state_failure_all_hidden_action">Gerir calendários</string>
<string name="state_failure_provider">Não foi possível ler o calendário.</string>
<string name="field_copy_action">Copiar</string>
<string name="field_copied">Copiado para a área de transferência</string>
<string name="field_copy_failed">Não foi possível copiar</string>
<string name="permission_rationale_title">Veja todos os seus eventos, lindamente</string>
<string name="permission_rationale_body">O Calendula precisa de aceder ao seu calendário para mostrar e gerir eventos. É tudo o que ele pede — e nada sai do seu dispositivo.</string>
<string name="permission_request_button">Conceder acesso ao calendário</string>
<string name="permission_denied_title">Acesso ao calendário negado</string>
<string name="permission_denied_body">O Calendula não consegue mostrar eventos sem acesso ao calendário. Pode concedê-lo novamente nas configurações do sistema.</string>
<string name="permission_open_settings_button">Abrir configurações do sistema</string>
<string name="permission_retry_button">Tentar novamente</string>
<string name="permission_benefit_private_title">Fica no seu dispositivo</string>
<string name="permission_benefit_private_body">Sem permissões de rede, sem telemetria — nada sai do seu telemóvel.</string>
<string name="permission_benefit_sync_title">Todos os seus calendários, juntos</string>
<string name="permission_benefit_sync_body">Google, CalDAV, local — tudo sincronizado ao dispositivo simplesmente aparece.</string>
<string name="permission_benefit_privacy_title">Nenhum rastreamento, jamais</string>
<string name="permission_benefit_privacy_body">Zero telemetria, zero dados para análise, sem anúncios.</string>
<string name="permission_privacy_footnote">Fica no seu dispositivo · sem permissão de internet</string>
<string name="month_prev">Mês anterior</string>
<string name="month_next">Mês seguinte</string>
<string name="month_today_action">Hoje</string>
<string name="month_more_actions">Mais ações</string>
<string name="month_open_menu">Abrir menu</string>
<string name="month_action_settings">Configurações</string>
<string name="month_a11y_today_prefix">Hoje</string>
<string name="week_today_action">Esta semana</string>
<string name="week_number_label">Sem</string>
<string name="day_today_action">Hoje</string>
<string name="event_detail_back">Voltar</string>
<string name="event_detail_edit">Editar</string>
<string name="event_detail_delete">Eliminar</string>
<string name="event_detail_share">Compartilhar</string>
<string name="event_detail_duplicate">Duplicar</string>
<string name="event_share_chooser_title">Compartilhar evento</string>
<string name="event_share_failed">Não foi possível compartilhar este evento.</string>
<string name="event_delete_title">Eliminar evento?</string>
<string name="event_delete_body">O evento será removido do seu calendário e de todos os aparelhos que o sincronizam.</string>
<string name="event_delete_recurring_title">Eliminar evento recorrente</string>
<string name="event_delete_option_occurrence">Apenas este evento</string>
<string name="event_delete_option_following">Este evento e todos os próximos</string>
<string name="event_delete_option_series">Todos os eventos nesta série</string>
<string name="event_edit_recurring_title">Editar evento recorrente</string>
<string name="event_delete_failed">Não foi possível eliminar o evento</string>
<string name="event_delete_write_denied">O Calendula requer permissão de escrita para excluir eventos</string>
<string name="event_move_action">Mover…</string>
<string name="event_move_recurring_title">Mover evento recorrente</string>
<string name="event_move_occurrence_only">Mover a série inteira mudaria os dias em que o evento cai, então somente este evento se pode mover.</string>
<string name="event_move_done">Movido para %1$s</string>
<string name="event_move_undo">Desfazer</string>
<string name="event_move_undone">Mover desfeito</string>
<string name="event_move_failed">Não foi possível mover o evento</string>
<string name="event_move_write_denied">O Calendula precisa de permissão de escrita para mover eventos</string>
<string name="event_move_gone">Este evento já não existe</string>
<string name="event_move_blocked_series_end">Impossível mover um evento após o fim da sua série</string>
<string name="dialog_cancel">Cancelar</string>
<string name="dialog_ok">OK</string>
<string name="event_edit_new_title">Novo evento</string>
<string name="event_edit_close">Fechar</string>
<string name="event_edit_save">Guardar</string>
<string name="event_edit_title_hint">Adicionar título</string>
<string name="event_edit_managed_hint">Gerido por “%1$s” — o título, data e frequência são sincronizados dos seus contactos. Os lembretes, os locais e as notas são seus para editar.</string>
<string name="event_edit_starts">Inicia</string>
<string name="event_edit_ends">Termina</string>
<string name="event_edit_error_end_before_start">Termina antes de iniciar</string>
<string name="event_edit_error_no_calendar">Nenhum calendário disponível para escrita</string>
<string name="event_edit_save_failed">Não foi possível guardar o evento</string>
<string name="event_edit_write_denied">O Calendula requer permissão de escrita para criar eventos</string>
<string name="event_edit_more_fields">Mais campos</string>
<string name="event_edit_add">Adicionar</string>
<string name="event_edit_add_reminder">Adicionar lembrete</string>
<string name="event_edit_remove_reminder">Remover lembrete</string>
<string name="event_edit_attendees">Convidados</string>
<string name="event_edit_add_guest">Adicionar convidado</string>
<string name="event_edit_add_guest_hint">Adicionar convidado via e-mail…</string>
<string name="event_edit_add_guest_from_contacts">Adicionar dos contactos</string>
<string name="event_edit_location_from_contacts">Escolher endereço dos contactos</string>
<string name="event_edit_remove_guest">Remover convidado</string>
<string name="event_edit_attendee_required">Obrigatório</string>
<string name="event_edit_attendee_optional">Opcional</string>
<string name="event_edit_attendees_note_synced">O Calendula não envia convites. A sua conta de calendário poderá enviar e-mails para os convidados quando sincronizar.</string>
<string name="event_edit_attendees_note_local">Armazenado neste dispositivo. Ninguém é notificado.</string>
<string name="event_edit_reminder_custom">Personalizado</string>
<string name="reminder_unit_minutes">minutos</string>
<string name="reminder_unit_hours">horas</string>
<string name="reminder_unit_days">dias</string>
<string name="event_edit_timezone_device_summary">Segue onde estiver</string>
<string name="event_edit_timezone_search">Procurar fusos horários</string>
<string name="event_edit_timezone_all">Todos os fusos horários</string>
<string name="reminder_unit_weeks">semanas</string>
<string name="event_edit_availability">Disponibilidade</string>
<string name="event_edit_visibility">Visibilidade</string>
<string name="event_edit_timezone_device">Fuso horário do dispositivo</string>
<string name="event_edit_timezone_recent">Recente</string>
<string name="event_edit_timezone_none">Nenhum fuso horário encontrado com “%1$s”</string>
<string name="event_edit_timezone_local_time">%1$s, no seu fuso horário</string>
<string name="event_edit_color_default">Cor do calendário</string>
<string name="event_edit_color">Cor</string>
<string name="event_edit_color_custom">Cor personalizada</string>
<string name="event_edit_color_reset">Redefinir</string>
<string name="event_edit_color_unsupported">Não disponível neste calendário</string>
<string name="event_edit_color_unsupported_hint">Este calendário não publica um esquema de cores. Pode permitir cores personalizadas nas Configurações.</string>
<string name="event_edit_color_sync_warning">Este calendário pode remover ou sobrescrever a cor na próxima sincronização.</string>
<string name="event_edit_conflict_title">Evento alterado noutro lugar</string>
<string name="event_edit_conflict_body">Enquanto estava a editar, este evento foi alterado — por sincronia ou por outra aplicação. O que fazer com as suas mudanças?</string>
<string name="event_edit_conflict_overwrite">Guardar mudanças</string>
<string name="event_edit_conflict_overwrite_hint">Apenas os campos editados sobrescrevem a mudança externa</string>
<string name="event_edit_conflict_discard">Descartar mudanças</string>
<string name="event_edit_conflict_discard_hint">O evento fica como está agora</string>
<string name="event_edit_gone_title">Evento eliminado</string>
<string name="event_edit_gone_body">Este evento foi entretanto eliminado, por exemplo, noutro aparelho. As suas mudanças já não podem ser guardadas.</string>
<string name="import_reminder_prompt_title">Aplicar o seu lembrete padrão?</string>
<string name="import_reminder_prompt_body_none">Este evento foi importado sem lembretes.</string>
<plurals name="import_reminder_prompt_body_existing">
<item quantity="one">Este evento foi importado com %1$d lembrete.</item>
<item quantity="many">Este evento foi importado com %1$d lembretes.</item>
<item quantity="other">Este evento foi importado com %1$d lembretes.</item>
</plurals>
<string name="import_reminder_prompt_apply">Aplicar o padrão</string>
<string name="import_reminder_prompt_keep">Manter assim</string>
<string name="event_edit_recurrence_none">Não se repete</string>
<string name="event_edit_recurrence_custom">Personalizado</string>
<string name="event_edit_recurrence_every">A cada</string>
<string name="recurrence_unit_days">dias</string>
<string name="recurrence_unit_weeks">semanas</string>
<string name="recurrence_unit_months">meses</string>
<string name="recurrence_unit_years">anos</string>
<string name="event_edit_recurrence_incomplete">Insira um número de 1 a 999</string>
<string name="event_edit_recurrence_next">Próximo: %1$s</string>
<string name="event_edit_recurrence_next_none">Esta regra nunca se repete</string>
<string name="event_edit_recurrence_ends">Termina</string>
<string name="event_edit_recurrence_end_never">Nunca</string>
<string name="event_edit_recurrence_end_until">Numa data</string>
<string name="event_edit_recurrence_end_count">Após um número de vezes</string>
<string name="event_edit_recurrence_times">vezes</string>
<string name="event_edit_error_recurrence_ends_before_start">As repetições terminam antes do evento começar</string>
<string name="event_availability_busy">Ocupado</string>
<string name="event_access_default">Padrão</string>
<string name="event_access_public">Público</string>
<string name="event_detail_all_day">O dia todo</string>
<string name="event_detail_calendar">Calendário</string>
<string name="event_detail_calendar_unknown">Calendário desconhecido</string>
<string name="event_detail_title">Título</string>
<string name="event_detail_location">Local</string>
<string name="event_detail_description">Descrição</string>
<string name="event_detail_attendees">Participantes</string>
<string name="event_detail_recurrence">Recorrência</string>
<string name="event_detail_recurring">Evento recorrente</string>
<string name="recurrence_daily">Todos os dias</string>
<string name="recurrence_weekly">Todas as semanas</string>
<string name="recurrence_monthly">Todos os meses</string>
<string name="recurrence_yearly">Todos os anos</string>
<string name="recurrence_every_n_days">A cada %1$d dias</string>
<string name="recurrence_every_n_weeks">A cada %1$d semanas</string>
<string name="recurrence_every_n_months">A cada %1$d meses</string>
<string name="recurrence_every_n_years">A cada %1$d anos</string>
<string name="recurrence_on_days">%1$s à %2$s</string>
<string name="recurrence_with_count">%1$s, %2$d vezes</string>
<string name="recurrence_with_until">%1$s até %2$s</string>
<string name="event_detail_not_found">Este evento já não existe.</string>
<string name="event_attendee_accepted">Aceitou</string>
<string name="event_attendee_declined">Rejeitou</string>
<string name="event_attendee_tentative">Não decidiu</string>
<string name="event_attendee_needs_action">Sem resposta</string>
<string name="event_attendee_unknown"></string>
<string name="event_detail_reminders">Lembretes</string>
<string name="event_detail_timezone">Fuso horário</string>
<string name="event_status_tentative">Talvez</string>
<string name="event_status_cancelled">Cancelado</string>
<string name="event_availability_free">Disponível</string>
<string name="event_access_private">Privado</string>
<string name="event_access_confidential">Confidencial</string>
<string name="event_access_public_summary">Todos com acesso veem tudo</string>
<string name="event_access_default_summary">O que este calendário normalmente faz</string>
<string name="event_access_private_summary">Os outros veem apenas que está ocupado</string>
<string name="event_access_confidential_summary">Marcado como confidencial; o que significa depende da conta</string>
<string name="event_attendee_organizer">Organizador</string>
<string name="event_attendee_optional">Opcional</string>
<string name="event_attendee_resource">Recurso</string>
<string name="event_detail_self_response">A sua resposta: %1$s</string>
<string name="reminder_at_time">Na hora do evento</string>
<string name="reminder_default">Lembrete padrão</string>
<string name="reminder_after">%1$s depois</string>
<plurals name="reminder_minutes">
<item quantity="one">%d minuto antes</item>
<item quantity="many">%d minutos antes</item>
<item quantity="other">%d minutos antes</item>
</plurals>
<plurals name="reminder_hours">
<item quantity="one">%d hora antes</item>
<item quantity="many">%d horas antes</item>
<item quantity="other">%d horas antes</item>
</plurals>
<plurals name="reminder_days">
<item quantity="one">%d dia antes</item>
<item quantity="many">%d dias antes</item>
<item quantity="other">%d dias antes</item>
</plurals>
<plurals name="reminder_weeks">
<item quantity="one">%d semana antes</item>
<item quantity="many">%d semanas antes</item>
<item quantity="other">%d semanas antes</item>
</plurals>
<plurals name="duration_minutes">
<item quantity="one">%d minuto</item>
<item quantity="many">%d minutos</item>
<item quantity="other">%d minutos</item>
</plurals>
<plurals name="duration_hours">
<item quantity="one">%d hora</item>
<item quantity="many">%d horas</item>
<item quantity="other">%d horas</item>
</plurals>
<plurals name="duration_days">
<item quantity="one">%d dia</item>
<item quantity="many">%d dias</item>
<item quantity="other">%d dias</item>
</plurals>
<string name="duration_hours_minutes">%1$s %2$s</string>
<string name="duration_custom_max">No máximo %1$s</string>
<plurals name="duration_weeks">
<item quantity="one">%d semana</item>
<item quantity="many">%d semanas</item>
<item quantity="other">%d semanas</item>
</plurals>
<string name="event_untitled">(Sem título)</string>
<string name="onboarding_step_counter">Passo %1$d de %2$d</string>
<string name="onboarding_backup_title">Os seus eventos vivem somente aqui</string>
<string name="onboarding_backup_body">Nada neste aparelho sincroniza para uma conta, ou seja, se o perder perde também o seu calendário. O Calendula pode criar um backup para si.</string>
<string name="onboarding_backup_benefit_folder_title">Uma pasta à sua escolha</string>
<string name="onboarding_backup_benefit_folder_body">Os backups são arquivos .ics — coloque-os num lugar para sincronizar, ou num cartão SD.</string>
<string name="onboarding_backup_benefit_daily_title">Uma vez por dia, sozinho</string>
<string name="onboarding_backup_benefit_daily_body">O Calendula exporta os seus calendários locais em segundo plano. Mude a frequência nas Configurações.</string>
<string name="onboarding_backup_enable_button">Escolher pasta e fazer backup</string>
<string name="onboarding_backup_skip_button">Agora não</string>
<string name="onboarding_view_title">O que deve abrir primeiro?</string>
<string name="onboarding_month_style_title">Como se deve o Mês parecer?</string>
<string name="onboarding_view_continue_button">Continuar</string>
<string name="onboarding_back">Voltar</string>
<string name="onboarding_visibility_button">Entendi</string>
<string name="onboarding_done_title">Tudo pronto</string>
<string name="onboarding_done_body">Os seus calendários estão prontos. Todas as suas escolhas podem ser alteradas depois nas Configurações.</string>
<string name="onboarding_done_button">Abrir o meu calendário</string>
<string name="reminder_channel_description">Notificações na hora dos lembretes dos seus eventos</string>
<string name="reminder_onboarding_title">Nunca perca um evento</string>
<string name="reminder_onboarding_body">O Android não mostra os seus lembretes sozinho — uma aplicação de calendário é que faz isso. Deixe o Calendula cuidar disso.</string>
<string name="reminder_benefit_delivery_title">Lembretes, entregues</string>
<string name="reminder_benefit_delivery_body">Todos os seus lembretes de evento chegam em notificação, na hora certa.</string>
<string name="reminder_benefit_duplicates_title">A usar outra aplicação de calendário?</string>
<string name="reminder_benefit_duplicates_body">Se outra aplicação também enviar lembretes, vê-los-á em dobro — desligue aqui ou lá.</string>
<string name="reminder_benefit_reversible_body">O botão está nas Configurações, dentro de Notificações.</string>
<string name="reminder_onboarding_enable_button">Ativar lembretes</string>
<string name="reminder_onboarding_skip_button">Agora não</string>
<string name="reminder_action_snooze">Soneca</string>
<string name="reminder_action_dismiss">Ignorar</string>
<string name="reminder_day_tomorrow">Amanhã</string>
<string name="reminder_day_yesterday">Ontem</string>
<string name="view_month">Mês</string>
<string name="view_week">Semana</string>
<string name="view_day">Dia</string>
<string name="view_agenda">Agenda</string>
<string name="view_section">Vista</string>
<string name="drawer_jump_to_date">Ir para data</string>
<string name="agenda_today_action">Hoje</string>
<string name="agenda_header_today">Hoje</string>
<string name="agenda_header_tomorrow">Amanhã</string>
<string name="agenda_empty_title">Tudo em dia</string>
<string name="agenda_no_more_today">Sem mais eventos hoje</string>
<string name="agenda_span_starts">Começa às %1$s</string>
<string name="agenda_span_ends">Termina às %1$s</string>
<string name="today_jump_action">Ir para Hoje</string>
<string name="search_action">Procurar</string>
<string name="search_hint">Procurar eventos</string>
<string name="search_back">Voltar</string>
<string name="search_idle_hint">Procure os seus eventos por título, local ou notas.</string>
<plurals name="search_selected_count">
<item quantity="one">%d selecionado</item>
<item quantity="many">%d selecionados</item>
<item quantity="other">%d selecionados</item>
</plurals>
<string name="search_in_descriptions">Encontrado em descrições</string>
<string name="search_selection_close">Cancelar seleção</string>
<string name="search_select_all">Selecionar tudo</string>
<string name="search_delete_selected">Eliminar selecionados</string>
<plurals name="search_delete_title">
<item quantity="one">Eliminar %d evento?</item>
<item quantity="many">Eliminar %d eventos?</item>
<item quantity="other">Eliminar %d eventos?</item>
</plurals>
<plurals name="search_delete_done">
<item quantity="one">%d evento eliminado</item>
<item quantity="many">%d eventos eliminados</item>
<item quantity="other">%d eventos eliminados</item>
</plurals>
<string name="search_delete_partial">%1$d eliminado(s), %2$d não puderam ser eliminado(s)</string>
<string name="search_delete_denied_partial">%1$d eliminado(s), e depois a permissão de escrita foi removida</string>
<string name="widget_agenda_title">A seguir</string>
<string name="widget_agenda_label">Agenda do Calendula</string>
<string name="widget_month_label">Mês do Calendula</string>
<string name="widget_refresh">Atualizar</string>
<string name="widget_new_event">Novo evento</string>
<string name="widget_needs_permission">Abra o Calendula para conceder acesso ao calendário</string>
<string name="widget_prev_month">Mês passado</string>
<string name="widget_next_month">Mês seguinte</string>
<string name="widget_today">Hoje</string>
<string name="filter_title">Calendários</string>
<string name="settings_title">Configurações</string>
<string name="search_empty">Nenhum evento corresponde a \"%1$s\".</string>
<string name="search_clear">Limpar</string>
<string name="reminder_benefit_reversible_title">Mude a qualquer hora</string>
<string name="reminder_channel_name">Lembretes de evento</string>
<string name="settings_back">Voltar</string>
<string name="back">Voltar</string>
<string name="settings_section_appearance">Aparência</string>
<string name="settings_theme">Tema</string>
<string name="settings_theme_system">Sistema</string>
<string name="settings_theme_light">Claro</string>
<string name="settings_theme_dark">Escuro</string>
<string name="settings_theme_hint">Se a aplicação é clara ou escura. Aplica imediatamente.</string>
<string name="settings_theme_system_summary">De momento %1$s</string>
<string name="settings_default_view">Vista padrão</string>
<string name="settings_dynamic_color">Cor dinâmica</string>
<string name="settings_dynamic_color_unavailable">Requer Android 12 ou mais recente</string>
<string name="settings_soften_colors">Harmonizar cores do calendário</string>
<string name="settings_soften_colors_summary">Mantenha cada tom do calendário mas equilibre os brilhos, para que cada evento continue legível e as cores combinem. Desative para mostrar as cores brutas da fonte do calendário.</string>
<string name="settings_font_headings">Fonte dos cabeçalhos</string>
<string name="settings_font_body">Fonte do corpo</string>
<string name="settings_font_system">Padrão do sistema</string>
<string name="font_atkinson_hyperlegible">Atkinson Hyperlegible</string>
<string name="font_lora">Lora</string>
<string name="font_jetbrains_mono">JetBrains Mono</string>
<string name="settings_font_choose_file">Escolher arquivo…</string>
<string name="settings_font_custom_selected">Fonte personalizada</string>
<string name="settings_font_import_failed">Não foi possível ler o ficheiro como fonte</string>
<string name="settings_font_specimen_heading">Quinta-feira, 14 de maio</string>
<string name="settings_font_specimen_body">Reunião de equipa às 10:00, depois almoço com a Robin no café em Markplatz.</string>
<string name="settings_week_start">A semana começa no/na</string>
<string name="settings_week_start_auto">Automático</string>
<string name="settings_week_start_auto_summary">De momento %1$s</string>
<string name="settings_week_numbers">Números das semanas</string>
<string name="settings_week_numbers_summary">Mostrar números das semanas na vista do mês</string>
<string name="settings_today_toolbar">Botão \"Hoje\" na barra de ferramentas</string>
<string name="settings_today_toolbar_summary">Mostrar um botão \"Hoje\" na barra de ferramentas em vez de um botão flutuante</string>
<string name="settings_app_name">Nome da aplicação</string>
<string name="settings_app_name_summary">Mostrar o Calendula como “Calendário” no seu launcher. Somente o nome do launcher muda; o ícone pode mudar para outro lugar após a troca.</string>
<string name="settings_time_format">Formato da hora</string>
<string name="settings_time_format_auto">Automático</string>
<string name="settings_time_format_12h">12 horas (2:00 PM)</string>
<string name="settings_time_format_24h">24 horas (14:00)</string>
<string name="settings_time_format_auto_summary">A seguir o sistema: %1$s</string>
<string name="settings_hour_lines">Grelha de horas</string>
<string name="settings_hour_lines_summary">Colocar cada hora na sua própria célula nas vistas Semana e Dia</string>
<string name="settings_timeline_scale">Altura da hora</string>
<string name="settings_timeline_scale_hint">Quanto espaço vertical que a hora ocupa nas vistas Semana e Dia. Ambas as vistas partilham este ajuste. Pode também pinçar a linha do tempo com dois dedos para definir outra altura.</string>
<string name="timeline_scale_fit_day">Encaixar o dia todo</string>
<string name="timeline_scale_fit_day_summary">24 horas no ecrã, sem scroll</string>
<string name="timeline_scale_compact">Compacto</string>
<string name="timeline_scale_compact_summary">Mais horas por ecrã, blocos menores</string>
<string name="timeline_scale_regular">Normal</string>
<string name="timeline_scale_regular_summary">Espaçamento padrão</string>
<string name="timeline_scale_comfortable">Confortável</string>
<string name="timeline_scale_comfortable_summary">Blocos maiores, mais scroll</string>
<string name="timeline_scale_custom">Personalizado</string>
<string name="timeline_scale_custom_summary">A altura em que pinçou a linha do tempo</string>
<string name="settings_dim_completed">Esmaecer eventos passados</string>
<string name="settings_dim_completed_summary">Esmaecer eventos que já terminaram nas vistas do mês e semana</string>
<string name="settings_drag_to_reschedule">Arrastar para reagendar</string>
<string name="settings_drag_to_reschedule_summary">Mova um evento arrastando-o para outro dia ou hora</string>
<string name="settings_past_events">Eventos passados</string>
<string name="settings_past_events_show">Mostrar</string>
<string name="settings_past_events_dim">Esmaecer</string>
<string name="settings_past_events_hide">Ocultar</string>
<string name="settings_past_events_sample_morning">Revisão da equipa</string>
<string name="settings_past_events_sample_midday">Almoço com a Robin</string>
<string name="settings_past_events_sample_evening">Treino do coro</string>
<string name="settings_agenda_header">Agenda</string>
<string name="settings_agenda_range">Amplitude da agenda</string>
<string name="settings_agenda_range_hint">O quanto à frente o ecrã da Agenda lista eventos.</string>
<string name="settings_agenda_widget_range">Amplitude do widget de Agenda</string>
<string name="settings_agenda_widget_range_hint">O quanto à frente o widget de Agenda lista eventos.</string>
<string name="settings_widget_size">Tamanho do widget de Agenda</string>
<string name="settings_widget_size_hint">Quão grande é o texto do widget de Agenda. O widget de mês não tem ajuste — a sua grelha encaixa sempre no espaço dado.</string>
<string name="settings_widget_size_small">Pequeno</string>
<string name="settings_widget_size_medium">Médio</string>
<string name="settings_widget_size_large">Grande</string>
<string name="settings_widget_size_extra_large">Extra grande</string>
<string name="settings_widget_size_summary">Texto do evento %1$d%%</string>
<string name="settings_agenda_show_today">Mostrar sempre Hoje</string>
<string name="settings_agenda_show_today_hint">Manter o dia de hoje no topo da agenda e no widget, mesmo que não tenha mais nada hoje.</string>
<string name="settings_agenda_range_bar">Barra de amplitude</string>
<string name="settings_agenda_range_bar_hint">Mostrar uma barra no topo da agenda a nomear as datas mostradas, com um botão para mudar a amplitude durante a sessão</string>
<string name="agenda_range_day">Hoje</string>
<string name="agenda_range_this_week">Esta semana</string>
<string name="agenda_range_this_month">Este mês</string>
<string name="agenda_range_week">Nos próximos 7 dias</string>
<string name="agenda_range_month">Nos próximos 30 dias</string>
<string name="agenda_range_custom">Personalizado…</string>
<string name="agenda_range_custom_hint">Dias</string>
<string name="agenda_range_override_hint">Só por enquanto — reajusta para a amplitude guardada ao reabrir o Calendula.</string>
<string name="agenda_range_showing_label">A mostrar todos os eventos nos próximos</string>
<plurals name="agenda_range_days">
<item quantity="one">%d dia</item>
<item quantity="many">%d dias</item>
<item quantity="other">%d dias</item>
</plurals>
<string name="settings_section_views">Vistas</string>
<string name="settings_month_header">Vista do Mês</string>
<string name="settings_month_view_style">Estilo de vista do Mês</string>
<string name="month_style_paged">Páginas</string>
<string name="month_style_paged_summary">Um mês ocupa o ecrã. Deslize para os lados para mudar o mês.</string>
<string name="month_style_continuous">Meses contínuos</string>
<string name="month_style_continuous_summary">Cada mês tem o próprio cabeçalho, com um espaço a separá-lo do próximo.</string>
<string name="month_style_dense">Semanas integradas</string>
<string name="month_style_dense_summary">As semanas seguem sem separação, com cada mês a terminar no início do outro sem distinção entre eles.</string>
<string name="month_style_split">Dividido</string>
<string name="month_style_split_summary">Uma grelha compacta marca os dias com eventos, e o dia clicado é listado abaixo.</string>
<string name="month_split_no_events">Nada agendado</string>
<string name="month_split_expand">Mostrar o mês inteiro</string>
<string name="month_split_collapse">Mostrar os eventos do dia</string>
<string name="settings_quick_switch_header">Botão de troca rápida</string>
<string name="settings_quick_switch_hint">Escolha que vistas pelas quais o botão no canto superior direito circula, e arraste para as ordenar. Com menos de duas vistas ligadas o botão é escondido. As vistas desligadas continuam acessíveis pelo menu de navegação.</string>
<string name="settings_drawer_order_header">Menu de navegação</string>
<string name="settings_drawer_order_hint">Arraste para reordenar as vistas listadas no menu de navegação.</string>
<string name="reorder_drag_handle">Arraste para reordenar</string>
<string name="settings_section_event_form">Novo formulário de evento</string>
<string name="settings_form_fields_hint">Campos padrão — o restante está dentro de \"Mais campos\"</string>
<string name="settings_autofocus_title">Focar no título num novo evento</string>
<string name="settings_autofocus_title_hint">Ao iniciar um novo evento, colocar o cursor no campo de título e abrir o teclado.</string>
<string name="settings_event_duration">Duração padrão</string>
<string name="settings_event_duration_hint">Quanto tempo um novo evento dura até mudar o término. Os eventos de dia inteiro não são afetados.</string>
<string name="settings_calendar_durations_title">Duração por calendário</string>
<string name="settings_calendar_durations_hint">Dar a um calendário a sua própria duração padrão — ex.: 8 horas para trabalho.</string>
<string name="settings_calendar_duration_inherits">Padrão (%1$s)</string>
<string name="settings_calendar_duration_use_default">Usar duração padrão (%1$s)</string>
<string name="settings_color_unsupported">Permitir cores em calendários não suportados</string>
<string name="settings_color_unsupported_hint">Alguns calendários (ex.: certos CalDAV) não publicam cores; uma cor de evento personalizada pode ser apagada ou sobrescrita na próxima sincronização. Esta é uma limitação destes calendários, e não é algo que o Calendula pode arranjar.</string>
<string name="settings_section_notifications">Notificações</string>
<string name="settings_reminders">Lembretes de evento</string>
<string name="settings_reminders_hint">Vê lembretes em duplicado ? Outra aplicação de calendário está a enviá-los — desligue num dos dois.</string>
<string name="settings_default_reminder">Lembrete padrão</string>
<string name="settings_default_reminder_allday">Eventos de dia todo</string>
<string name="settings_allday_reminder_time">Hora de lembrete de evento de dia todo</string>
<string name="settings_allday_reminder_time_hint">Os lembretes para eventos de dia todo disparam às %1$s</string>
<string name="settings_allday_reminder_fires_at">Notifica às %1$s</string>
<string name="reminder_none">Nenhum</string>
<string name="reminder_use_default">Usar lembrete padrão</string>
<string name="reminder_custom_amount">Quantidade</string>
<string name="reminder_custom_set">Ajustar</string>
<string name="settings_calendar_reminders_title">Lembretes por calendário</string>
<string name="settings_calendar_reminders_hint">Mude o padrão por calendário — separadamente para eventos com horário e de dia todo. Um calendário pode manter o padrão, removê-lo, ou ajustar o seu próprio.</string>
<string name="settings_calendar_reminder_inherits">Padrão (%1$s)</string>
<string name="settings_reliable_delivery">Entrega confiável</string>
<string name="settings_reliable_delivery_hint">O Android pode atrasar lembretes para economizar bateria. Autorize o Calendula para que possam chegar na hora.</string>
<string name="settings_reliable_delivery_exempt">Isentar de otimização de bateria — os lembretes chegam na hora.</string>
<string name="settings_snooze_duration">Duração da soneca</string>
<string name="settings_section_calendars">Calendários</string>
<string name="settings_manage_calendars">Gerir calendários</string>
<string name="settings_manage_calendars_hint">Crie calendários locais; gira os sincronizados</string>
<string name="settings_section_language">Idioma</string>
<string name="settings_language">Idioma da aplicação</string>
<string name="settings_language_auto">Padrão do sistema</string>
<string name="settings_translate">Ajude a traduzir</string>
<string name="settings_translate_hint">Adicione ou melhore um idioma no Weblate</string>
<string name="settings_group_look">Aparência e comportamento</string>
<string name="settings_group_data">Dados</string>
<string name="settings_group_app">Aplicação</string>
<string name="settings_group_about">Sobre</string>
<string name="settings_appearance_subtitle">Tema, cores, fontes</string>
<string name="settings_views_subtitle">Vista, layout e ordem padrão</string>
<string name="settings_event_form_subtitle">Campos e comportamento padrão</string>
<string name="settings_notifications_subtitle">Lembretes e entrega</string>
<string name="settings_special_dates_subtitle">Aniversários e datas de contacto</string>
<string name="settings_widgets_subtitle">Widget de Agenda, bloco de Ajustes Rápidos</string>
<string name="settings_backup_subtitle">Exportar, importar, backup automático</string>
<string name="settings_section_widgets">Widgets e blocos</string>
<string name="settings_widgets_hint">Ajustes para os widgets do ecrã inicial e para o bloco de Ajustes Rápidos. Adicione um widget pressionando e segurando o ecrã inicial.</string>
<string name="settings_section_backup">Backup e restauro</string>
<string name="settings_views_all_header">Todas as vistas</string>
<string name="settings_week_day_header">Semana e dia</string>
<string name="settings_default_view_hint">A vista que o Calendula abre ao iniciar.</string>
<string name="settings_week_start_hint">O dia em que cada semana inicia, em todas as vistas e widgets.</string>
<string name="settings_time_format_hint">Como as horas são escritas pela aplicação. \"Automático\" segue a configuração do sistema.</string>
<string name="settings_past_events_hint">O que a agenda faz com eventos que já terminaram.</string>
<string name="settings_dynamic_color_summary">Use as cores da aplicação de acordo com seu papel de parede.</string>
<string name="settings_section_special_dates">Datas especiais de contactos</string>
<string name="settings_special_dates_enable">Mostrar datas de contactos</string>
<string name="settings_special_dates_enable_hint">Copiar os aniversários e outras datas dos contactos para calendários locais. Lê os contatos somente neste aparelho — nada é enviado, e seus contatos nunca são alterados.</string>
<string name="settings_special_dates_type_birthday">Aniversários</string>
<string name="settings_special_dates_type_anniversary">Aniversários de relacionamentos</string>
<string name="settings_special_dates_type_custom">Outras datas</string>
<string name="settings_special_dates_template">Formato do título</string>
<string name="settings_special_dates_template_hint">Use {nome} para o contacto e {ano} para o ano (de nascimento, ou de início do relacionamento; oculto quando desconhecido).</string>
</resources>
+11
View File
@@ -344,4 +344,15 @@
<string name="settings_week_start">Неделя начинается в</string>
<string name="settings_week_start_auto">Автоматически</string>
<string name="settings_week_start_auto_summary">Выбрано: %1$s</string>
<string name="state_failure_all_hidden_action">Управление календарями</string>
<string name="field_copy_action">Копировать</string>
<string name="field_copied">Скопировано в буфер обмена</string>
<string name="event_detail_title">Заголовок</string>
<string name="settings_week_numbers">Номер недели</string>
<string name="settings_app_name">Имя приложения</string>
<string name="settings_app_name_summary">Отображать Calendula как “Календарь” в вашем лаунчере. Изменяется только отображаемое имя в лаунчере; иконка может переместиться на новое место после включения.</string>
<string name="settings_time_format">Формат времени</string>
<string name="settings_time_format_auto">Автоматически</string>
<string name="settings_time_format_12h">12-часовой формат времени</string>
<string name="settings_time_format_24h">24-часовой формат времени</string>
</resources>
@@ -598,12 +598,9 @@
<string name="crash_dialog_message">%1$s 上次意外关闭。您可以将此报告作为问题发送以帮助修复。报告在您选择共享之前仅保留在设备上,不含任何个人数据或日历内容——仅包含以下技术细节。</string>
<string name="crash_dialog_report">报告</string>
<string name="crash_dialog_dismiss">暂不</string>
<string name="crash_report_issue_title">崩溃报告</string>
<string name="crash_report_clip_label">%1$s 崩溃报告</string>
<string name="crash_report_copied">报告已复制到剪贴板</string>
<string name="crash_report_open_failed">无法打开问题追踪器。报告已在剪贴板中。</string>
<string name="crash_report_body_template">感谢您报告 %1$s 的崩溃。请补充您记得的操作内容,然后提交。\n\n### 发生了什么\n\n\n### 崩溃报告\n%2$s\n</string>
<string name="crash_report_body_paste">_(报告太长,无法通过此链接附带——请从剪贴板粘贴。)_</string>
<string name="special_dates_calendar_birthday">生日</string>
<string name="special_dates_calendar_anniversary">纪念日</string>
<string name="special_dates_calendar_custom">特殊日期</string>
+2 -3
View File
@@ -14,6 +14,8 @@
<string name="state_failure_permission_action">Grant access</string>
<string name="state_failure_no_calendars">No calendars configured.</string>
<string name="state_failure_no_calendars_action">Open system calendar settings</string>
<string name="state_failure_all_hidden">All your calendars are switched off.</string>
<string name="state_failure_all_hidden_action">Manage calendars</string>
<string name="state_failure_provider">Could not read the calendar.</string>
<!-- Long-press a field to copy it (#195) -->
@@ -772,12 +774,9 @@
<string name="crash_dialog_message">%1$s closed unexpectedly last time. You can help fix it by sending this report as an issue. It stays on your device until you choose to share it, and includes no personal data or calendar content — only the technical details below.</string>
<string name="crash_dialog_report">Report</string>
<string name="crash_dialog_dismiss">Not now</string>
<string name="crash_report_issue_title">Crash report</string>
<string name="crash_report_clip_label">%1$s crash report</string>
<string name="crash_report_copied">Report copied to your clipboard</string>
<string name="crash_report_open_failed">Couldn\'t open the issue tracker. The report is on your clipboard.</string>
<string name="crash_report_body_template">Thanks for reporting a crash in %1$s. Please add anything you remember about what you were doing, then submit.\n\n### What happened\n\n\n### Crash report\n%2$s\n</string>
<string name="crash_report_body_paste">_(The report was too long for this link — paste it from your clipboard here.)_</string>
<string name="report_issue_url" translatable="false">https://codeberg.org/jlmakiola/calendula/issues/new</string>
<string name="report_issue_choose_url" translatable="false">https://codeberg.org/jlmakiola/calendula/issues/new/choose</string>
@@ -121,4 +121,24 @@ class CalendarVisibilityPlanTest {
),
).isTrue()
}
@Test
fun `no calendars on the device is its own failure`() {
assertThat(calendarListFailure(emptyList()))
.isEqualTo(FailureReason.NoCalendarsConfigured)
}
@Test
fun `calendars that are all switched off read as hidden, not missing`() {
// The remedy differs: one needs a calendar made, the other needs one
// switched back on (#239).
assertThat(calendarListFailure(listOf(cal(1L, visible = false), cal(2L, visible = false))))
.isEqualTo(FailureReason.AllCalendarsHidden)
}
@Test
fun `one visible calendar is enough to show something`() {
assertThat(calendarListFailure(listOf(cal(1L, visible = false), cal(2L, visible = true))))
.isNull()
}
}
@@ -36,11 +36,12 @@ class ModelsTest {
}
@Test
fun `FailureReason enum has all five variants`() {
fun `FailureReason enum has all six variants`() {
assertThat(FailureReason.values().toSet()).isEqualTo(
setOf(
FailureReason.PermissionRevoked,
FailureReason.NoCalendarsConfigured,
FailureReason.AllCalendarsHidden,
FailureReason.ProviderUnavailable,
FailureReason.EventNotFound,
FailureReason.Unknown,
+117
View File
@@ -0,0 +1,117 @@
---
title: Privacy Policy — Calendula
description: What Calendula does with your data. It collects nothing, sends nothing, and has no internet permission at all.
updated: 2026-07-28
---
<!--
THIS FILE IS THE POLICY. Edit it here, in a PR, reviewed like any other
change — it is the source of truth.
It is published at https://jeanlucmakiola.de/calendula/privacy, which is what
the app's Settings → About → Privacy policy row opens and what the Play
Console field must hold. That page holds no copy of the prose: the website
build checks this repository out beside itself and renders this file through
an Astro content collection, so there is exactly one copy of the policy
anywhere and the two cannot drift. An edit here reaches the live page on the
site's next build.
The page supplies its own <h1> from the `title` above, so this body starts at
the first section — do not add one. This comment is HTML so that it cannot
render on the published page.
-->
**Last updated:** 28 July 2026
Applies to the Android app **Calendula** (package `de.jeanlucmakiola.calendula`), all versions and all distribution channels.
## In short
Calendula collects nothing, sends nothing, and has no user accounts. It has **no internet permission at all** — the app is technically incapable of transmitting your data anywhere. Everything it shows you is read from the calendars that already exist on your device.
## 1. Controller
IT-Dienstleister | Jean-Luc Makiola
Mahlerstraße 10
14772 Brandenburg an der Havel
Email: [business@jeanlucmakiola.de](mailto:business@jeanlucmakiola.de)
## 2. No data collection
Calendula contains **no analytics, no tracking, no advertising, no crash-reporting SDK and no third-party services of any kind**. No user profile is created, no identifier is generated, and no data is shared with or sold to anyone.
The app does not request the `android.permission.INTERNET` permission. Without it, Android prevents the app from opening any network connection. This is verifiable: inspect the permission list of any released APK, or read the [source code](https://codeberg.org/jlmakiola/calendula).
## 3. Data Calendula accesses on your device
All of the following is processed **locally on your device only**. None of it is transmitted, and none of it is stored by the developer.
### Calendar data
Calendula is a viewer and editor for the calendars Android already manages. It reads and writes events, reminders and calendar settings through Android's system calendar provider. The app keeps **no database of its own** — your events live in the system calendar, exactly where they lived before you installed Calendula, and they remain there if you uninstall it.
Note: if one of those system calendars is itself synchronised with an online account (for example a Google account, or a CalDAV server via DAVx5), that synchronisation is performed by Android and that other app — not by Calendula. The privacy policy of the respective provider applies to it.
### Contacts (optional)
The “Contact special dates” feature reads birthdays and anniversaries from your contacts and mirrors them one-way into a local calendar, so they appear alongside your other events. This feature is switched off by default, the contacts permission is requested only when you enable it, and it is never requested at startup. Contacts are only ever read, never modified, and the data does not leave your device.
### Notifications
Reminders are displayed as local notifications on your device. Nothing is sent to a push service.
### Files
When you import or export an ICS file, Calendula reads or writes exactly the file you select through Android's system file picker. The optional automatic backup writes an ICS export to the folder you choose. The app has no access to other files.
### App settings
Your preferences (view options, theme, reminder defaults and similar) are stored locally on your device and are removed when you uninstall the app.
## 4. Crash reports — the only case where data can leave your device
If Calendula crashes, it offers to report the problem. Nothing is sent automatically. The report is copied to your clipboard and your browser is opened with the project's issue tracker, the text pre-filled. **You see the full content, you decide whether to submit it, and you can edit or discard it.**
Such a report contains:
- app version,
- Android version,
- device manufacturer and model,
- your device language,
- the timestamp,
- and the technical stack trace.
It contains **no** event data, **no** contacts and **no** personal identifiers.
If you choose to submit it, the report becomes a public issue on the project's issue tracker at Codeberg, operated by Codeberg e. V. Their privacy policy then applies to that submission.
## 5. External links
The settings screen contains links to the source code, the licence, the issue tracker and a voluntary donation page (Ko-fi). Following one of these links opens your browser and leaves the app; the privacy policy of the respective website then applies. Calendula transmits no data of yours in the process — it only opens the address.
## 6. Permissions and why they exist
- `READ_CALENDAR`, `WRITE_CALENDAR` — display and edit your events; the core function.
- `POST_NOTIFICATIONS` — show reminders.
- `READ_CONTACTS` — optional, only for the “Contact special dates” feature.
- `USE_EXACT_ALARM`, `SCHEDULE_EXACT_ALARM` — deliver reminders at the exact time, including after snoozing.
- `RECEIVE_BOOT_COMPLETED` — re-register pending reminders after a restart.
- `REQUEST_IGNORE_BATTERY_OPTIMIZATIONS` — only to open the system dialog for the “Reliable delivery” setting.
- `WAKE_LOCK`, `FOREGROUND_SERVICE`, `ACCESS_NETWORK_STATE` — required by the Android system component used for scheduled background work (WorkManager).
`ACCESS_NETWORK_STATE` allows reading *whether* a network connection exists — it does **not** permit using one. Without `INTERNET`, no connection is possible.
## 7. Distribution channels
Calendula is distributed via F-Droid, Obtainium, a self-hosted repository and, where applicable, the Google Play Store. When you download or update the app, the operator of that channel processes data (such as your IP address) under their own privacy policy. This is outside the developer's control and unrelated to the app's own behaviour.
## 8. Children
Calendula is suitable for all ages. Since it collects no data at all, no data of children is processed either.
## 9. Your rights
Because the developer processes no personal data of yours, there is no stored data to which rights of access, rectification, erasure, restriction, data portability or objection (Art. 1521 GDPR) could apply. You may nevertheless contact the address above at any time with any question. You also have the right to lodge a complaint with a supervisory authority.
## 10. Changes to this policy
Should the app's functionality change in a way that affects data processing, this policy will be updated and the date at the top adjusted. The version history is publicly traceable in the project's source repository.
@@ -0,0 +1,2 @@
إصلاحات
• لم يعد النطاق المخصص في الجدول يُعطِّل التطبيق بالفرنسية. كان اختيار نطاق مخصص — أو مجرّد كتابة رقم في ذلك الحقل — يُغلق التطبيق على أي هاتف مضبوط على الفرنسية، ولم ينجُ سوى نطاق يوم واحد بالضبط. أما اللغات الأخرى فلم تتأثّر قطّ.
@@ -0,0 +1,2 @@
Behoben
• Ein benutzerdefinierter Agenda-Zeitraum stürzt auf Französisch nicht mehr ab. Einen eigenen Zeitraum zu wählen oder auch nur eine Zahl in das Feld zu tippen beendete die App auf jedem Gerät mit französischer Sprache; nur genau ein Tag blieb verschont. Andere Sprachen waren nie betroffen.
@@ -0,0 +1,2 @@
Fixed
• A custom Agenda range no longer crashes the app in French. Choosing a custom range — or just typing a number into that field — closed the app on any phone set to French, and only a range of exactly one day escaped it. Other languages were never affected.
@@ -0,0 +1,11 @@
New
• Long-press an event's title, location or description to copy.
• Settings → About lists the open-source projects we ship.
Changed
• Week & day: each hour sits in its own cell, not a line.
• Unanswered invitations are drawn as outlines.
Fixed
• "No calendars configured" now really opens the system calendar setup.
• When every calendar is switched off, the app says so instead of a blank month.
@@ -0,0 +1,2 @@
Fixed
• Crash reports are now filed in English. On a phone set to another language, the prefilled issue's title and text came out in that language, which nobody on the project could read. What gets posted is English for everyone; the dialog asking you to send it stays in your language.
@@ -0,0 +1,2 @@
Fixed
• A custom Agenda range no longer crashes the app in French. Choosing a custom range — or just typing a number into that field — closed the app on any phone set to French, and only a range of exactly one day escaped it. Other languages were never affected.
@@ -0,0 +1,2 @@
Correcciones
• El intervalo personalizado de la Agenda ya no bloquea la aplicación en francés. Elegir un intervalo propio —o solo escribir un número en ese campo— cerraba la aplicación en cualquier teléfono en francés, y únicamente un intervalo de exactamente un día se salvaba. Los demás idiomas nunca se vieron afectados.
@@ -0,0 +1,2 @@
Corrections
• La plage personnalisée de lAgenda ne fait plus planter lapplication en français. Choisir une plage personnalisée — ou simplement saisir un nombre dans ce champ — fermait lapplication sur tout téléphone en français ; seule une plage dexactement un jour y échappait.
@@ -0,0 +1,2 @@
Correzioni
• Lintervallo personalizzato dellAgenda non fa più chiudere lapp in francese. Scegliere un intervallo personalizzato — o anche solo digitare un numero in quel campo — chiudeva lapp su qualsiasi telefono impostato in francese; solo un intervallo di esattamente un giorno ne era immune. Le altre lingue non sono mai state interessate.
@@ -0,0 +1,2 @@
Poprawki
• Niestandardowy zakres Agendy nie powoduje już awarii aplikacji w języku francuskim. Wybranie własnego zakresu albo samo wpisanie liczby w to pole zamykało aplikację na każdym telefonie ustawionym na francuski; bezpieczny był tylko zakres dokładnie jednego dnia. Innych języków to nigdy nie dotyczyło.
@@ -0,0 +1,2 @@
Correções
• O intervalo personalizado da Agenda não fecha mais o aplicativo em francês. Escolher um intervalo personalizado — ou apenas digitar um número nesse campo — fechava o aplicativo em qualquer telefone configurado em francês; só um intervalo de exatamente um dia escapava. Os outros idiomas nunca foram afetados.
@@ -0,0 +1,2 @@
Correções
• O intervalo personalizado da Agenda já não fecha a aplicação em francês. Escolher um intervalo personalizado — ou apenas escrever um número nesse campo — fechava a aplicação em qualquer telemóvel definido em francês; só um intervalo de exatamente um dia escapava. Os outros idiomas nunca foram afetados.
@@ -0,0 +1,2 @@
Исправлено
• Свой диапазон в Расписании больше не приводит к сбою на французском языке. Выбор своего диапазона — или даже простой ввод числа в это поле — закрывал приложение на любом телефоне с французским языком; уцелел только диапазон ровно в один день. Другие языки это никогда не затрагивало.
@@ -0,0 +1,2 @@
修复
• 法语下的日程自定义范围不再导致应用崩溃。选择自定义范围,甚至只是在该字段中输入数字,都会让应用在设置为法语的手机上关闭,只有恰好一天的范围不受影响。其他语言从未受到影响。
+46 -7
View File
@@ -8,7 +8,10 @@ and are produced via Weblate. This guard keeps incoming translation PRs honest:
* a translation must not define keys absent from the base those are stale
keys left behind after a rename/removal upstream;
* a translation must not translate strings marked ``translatable="false"`` in
the base (URLs, IDs and the like).
the base (URLs, IDs and the like);
* every translated ``<plurals>`` must carry an ``other`` item, because that
is the one quantity form Android cannot fall back for (see
``plurals_missing_other``).
Missing keys are *allowed* and only reported as coverage: a missing string
falls back to the English base at runtime, so partial translations are fine
@@ -27,10 +30,13 @@ RES_DIR = Path("app/src/main/res")
BASE = RES_DIR / "values" / "strings.xml"
RESOURCE_TAGS = ("string", "plurals", "string-array")
# The quantity Android itself falls back to, and therefore the one a translated
# <plurals> may never omit.
PLURAL_FALLBACK = "other"
def entries(path: Path) -> dict[str, bool]:
"""Map resource name -> is-translatable for every entry in ``path``."""
root = ET.parse(path).getroot()
def entries(root: ET.Element) -> dict[str, bool]:
"""Map resource name -> is-translatable for every entry under ``root``."""
return {
el.attrib["name"]: el.attrib.get("translatable", "true") != "false"
for el in root
@@ -38,12 +44,35 @@ def entries(path: Path) -> dict[str, bool]:
}
def plurals_missing_other(root: ET.Element) -> list[str]:
"""Names of ``<plurals>`` under ``root`` that lack an ``other`` item.
Android resolves the CLDR quantity for a count and, if that specific form is
absent, falls back to ``other`` so a translation may legitimately skip
forms its locale rarely uses (Arabic ``zero``, French ``many``). There is no
fallback for ``other`` itself, and none to the base locale either: a
translated ``<plurals>`` without it raises
``Resources$NotFoundException`` as soon as a count selects the missing form.
That is Codeberg #297/#298 — ``values-fr`` translated ``agenda_range_days``
with only ``one`` and ``many``, and since French ``many`` matches only
millions, every custom agenda range from 2 days up crashed the app.
"""
return sorted(
el.attrib["name"]
for el in root
if el.tag == "plurals"
and "name" in el.attrib
and not any(item.attrib.get("quantity") == PLURAL_FALLBACK for item in el.findall("item"))
)
def main() -> int:
if not BASE.exists():
print(f"::error::base resource file {BASE} not found", file=sys.stderr)
return 1
base = entries(BASE)
base = entries(ET.parse(BASE).getroot())
base_keys = set(base)
nontranslatable = {name for name, ok in base.items() if not ok}
translatable_total = len(base_keys - nontranslatable)
@@ -57,16 +86,18 @@ def main() -> int:
for path in files:
locale = path.parent.name[len("values-"):]
try:
translated = entries(path)
root = ET.parse(path).getroot()
except ET.ParseError as exc:
print(f"::error file={path}::{locale}: malformed XML: {exc}")
errors += 1
continue
translated = entries(root)
keys = set(translated)
stale = sorted(keys - base_keys)
translated_fixed = sorted(keys & nontranslatable)
missing = base_keys - nontranslatable - keys
no_other = plurals_missing_other(root)
for name in stale:
print(f"::error file={path}::{locale}: stale key '{name}' is not in the base strings.xml")
@@ -77,10 +108,18 @@ def main() -> int:
"in the base and must not be translated"
)
errors += 1
for name in no_other:
print(
f"::error file={path}::{locale}: plurals '{name}' has no "
f"<item quantity=\"{PLURAL_FALLBACK}\"> — Android cannot fall back for it "
"and will crash when a count selects it; translate that form or drop the "
"whole plurals to inherit the base"
)
errors += 1
covered = translatable_total - len(missing)
pct = covered * 100 // translatable_total if translatable_total else 100
verdict = "OK" if not (stale or translated_fixed) else "FAIL"
verdict = "OK" if not (stale or translated_fixed or no_other) else "FAIL"
print(f"{locale:<10} {covered}/{translatable_total} keys ({pct}%) — {verdict}")
if errors: