Compare commits

...
Author SHA1 Message Date
makiolaj 641494dad4 Release v2.22.3: restore the Calendar suffix in the store title (#361)
Closes #361
2026-10-02 22:01:24 +02:00
Jean-Luc Makiola 99bb6adf80 Release v2.22.2 (#360)
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 14m8s
Release — F-Droid repo + Gitea/Codeberg release + Play / play (push) Successful in 2m59s
Patch release for #359. No app changes.

- The Dutch store listing moved from `fastlane/metadata/android/nl` to `nl-NL`. Play rejects plain `nl`, so the Play upload of 2.22.0 and 2.22.1 failed with `nl - Invalid request`. F-Droid accepts either code.
- `check_store_listing.py` now checks every store code in `store-locales.txt` against the languages Play accepts, so CI catches this before a release.
- The 22202 "What's New" covers the 2.22 highlights, since Play users go straight from 2.21.0 to 2.22.2, and says the app is the same as 2.22.1.

Closes #359
2026-10-02 20:41:17 +02:00
Jean-Luc Makiola 06ee010f07 Release v2.22.1 (#358)
Release — F-Droid repo + Gitea/Codeberg release + Play / detect (push) Successful in 10s
Release — F-Droid repo + Gitea/Codeberg release + Play / release (push) Successful in 14m6s
Release — F-Droid repo + Gitea/Codeberg release + Play / play (push) Failing after 1m28s
Patch release for #357.

- Tapping a meeting link in an event's location opened it in a maps app. Links in the location are now underlined and open in the browser, the same way description links do. Tapping the rest of the location still opens maps, so a location with both an address and a link works for both.
- Link detection moved into `WebLinks.kt` with unit tests. It now matches a capitalised scheme (`Https://`), lower-cases the scheme before launching, and leaves `<…>` out of the URL (the Outlook/Teams style). This applies to description links too.
- Links open with `CATEGORY_BROWSABLE` through one helper. A failed launch shows a "No app can open this link" toast instead of doing nothing or crashing on a `SecurityException`.
- The location's maps tap has an "Open in maps" accessibility label (new `onTapLabel` on `copyOnLongPress`).

The issue only asked for links to open in the browser. Inline links instead of switching the whole tap target came out of review: they keep the address reachable when a location holds both.

Plus the release commit: CHANGELOG section, versionName 2.22.1 / versionCode 22201, and the 22201 changelogs for every store locale. Merging this to main triggers the release pipeline.

Closes #357
2026-10-02 18:45:38 +02:00
82 changed files with 331 additions and 53 deletions
+18
View File
@@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## [2.22.3] — 2026-10-02
### Fixed
- **The store listing is called "Calendula: Calendar" again,** with "Calendar" in each store language. Since 2.22.0 the Play listing comes from the repository, whose title was only "Calendula". The app is unchanged ([#361]).
## [2.22.2] — 2026-10-02
### Fixed
- **2.22 reaches Google Play.** The Dutch store listing used the locale code `nl`, which Play rejects, so the Play uploads of 2.22.0 and 2.22.1 failed. It now uses `nl-NL`, and CI checks every store locale against the codes Play accepts. The app is unchanged from 2.22.1 ([#359]).
## [2.22.1] — 2026-10-02
### Fixed
- **Tapping a link in an event's location opens it in the browser instead of a maps app.** Links are underlined, as in the description, and tapping the rest of the location still opens maps. A link with a capitalised `Https://`, or wrapped in `<…>` the way Outlook and Teams write them, opens correctly too. When no app can open a link, a short message says so instead of the tap doing nothing ([#357]).
## [2.22.0] — 2026-10-01 ## [2.22.0] — 2026-10-01
### Added ### Added
@@ -1817,3 +1832,6 @@ automatically, with zero telemetry and no internet permission.
[#322]: https://codeberg.org/jlmakiola/calendula/issues/322 [#322]: https://codeberg.org/jlmakiola/calendula/issues/322
[#331]: https://codeberg.org/jlmakiola/calendula/issues/331 [#331]: https://codeberg.org/jlmakiola/calendula/issues/331
[#336]: https://codeberg.org/jlmakiola/calendula/issues/336 [#336]: https://codeberg.org/jlmakiola/calendula/issues/336
[#357]: https://codeberg.org/jlmakiola/calendula/issues/357
[#359]: https://codeberg.org/jlmakiola/calendula/issues/359
[#361]: https://codeberg.org/jlmakiola/calendula/issues/361
+2 -2
View File
@@ -28,8 +28,8 @@ android {
// which builds this version and then creates the matching vX.Y.Z tag + // which builds this version and then creates the matching vX.Y.Z tag +
// release itself (versionCode is pinned to MAJOR*10000 + MINOR*100 + // release itself (versionCode is pinned to MAJOR*10000 + MINOR*100 +
// PATCH from versionName, e.g. 2.7.2 -> 20702). See docs/RELEASING.md. // PATCH from versionName, e.g. 2.7.2 -> 20702). See docs/RELEASING.md.
versionCode = 22200 versionCode = 22203
versionName = "2.22.0" versionName = "2.22.3"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
} }
@@ -65,9 +65,9 @@ fun rememberFieldCopier(snackbarHostState: SnackbarHostState): FieldCopier {
/** /**
* Long-press to copy [text] whole, filed on the clipboard under [label]. * Long-press to copy [text] whole, filed on the clipboard under [label].
* *
* [onTap] carries a field's existing tap action through; a field without one * [onTap] carries a field's existing tap action through, announced as
* stays unclickable rather than growing a ripple that leads nowhere, and gets * [onTapLabel]; a field without one stays unclickable rather than growing a
* its long press announced through semantics instead. That branch merges the * ripple that leads nowhere, and gets its long press announced through semantics instead. That branch merges the
* node it sits on, so a screen reader lands on the field itself and finds the * node it sits on, so a screen reader lands on the field itself and finds the
* action there — a bare container is never focused. * action there — a bare container is never focused.
*/ */
@@ -77,11 +77,13 @@ fun Modifier.copyOnLongPress(
text: String, text: String,
copy: FieldCopier, copy: FieldCopier,
onTap: (() -> Unit)? = null, onTap: (() -> Unit)? = null,
onTapLabel: String? = null,
): Modifier { ): Modifier {
val actionLabel = stringResource(R.string.field_copy_action) val actionLabel = stringResource(R.string.field_copy_action)
return if (onTap != null) { return if (onTap != null) {
combinedClickable( combinedClickable(
onClick = onTap, onClick = onTap,
onClickLabel = onTapLabel,
onLongClickLabel = actionLabel, onLongClickLabel = actionLabel,
onLongClick = { copy(label, text) }, onLongClick = { copy(label, text) },
) )
@@ -1,11 +1,11 @@
package de.jeanlucmakiola.calendula.ui.detail package de.jeanlucmakiola.calendula.ui.detail
import android.Manifest import android.Manifest
import android.content.ActivityNotFoundException
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.net.Uri import android.net.Uri
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.background import androidx.compose.foundation.background
@@ -534,7 +534,7 @@ private fun EventDetailContent(
) )
} }
// Location (conditional, tap → maps). // Location (conditional). URLs open in the browser, the rest in maps.
instance.location?.takeIf { it.isNotBlank() }?.let { location -> instance.location?.takeIf { it.isNotBlank() }?.let { location ->
val context = LocalContext.current val context = LocalContext.current
val locationLabel = stringResource(R.string.event_detail_location) val locationLabel = stringResource(R.string.event_detail_location)
@@ -544,7 +544,7 @@ private fun EventDetailContent(
iconContentDescription = locationLabel, iconContentDescription = locationLabel,
) { ) {
Text( Text(
text = location, text = linkifyUrls(location, MaterialTheme.colorScheme.primary),
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.primary, color = MaterialTheme.colorScheme.primary,
modifier = Modifier modifier = Modifier
@@ -554,6 +554,7 @@ private fun EventDetailContent(
text = location, text = location,
copy = copyField, copy = copyField,
onTap = { openInMaps(context, location) }, onTap = { openInMaps(context, location) },
onTapLabel = stringResource(R.string.event_detail_open_in_maps),
) )
.padding(vertical = 2.dp), .padding(vertical = 2.dp),
) )
@@ -846,21 +847,23 @@ private fun foreignTimeZone(
) )
} }
/** Wrap http(s) URLs in [text] as tappable links tinted [linkColor]. */ /** Wrap http(s) URLs in [text] as links tinted [linkColor] that open in the browser. */
@Composable @Composable
private fun linkifyUrls(text: String, linkColor: Color): AnnotatedString = remember(text, linkColor) { private fun linkifyUrls(text: String, linkColor: Color): AnnotatedString {
val regex = Regex("""https?://\S+""") val context = LocalContext.current
val styles = TextLinkStyles( return remember(text, linkColor, context) {
style = SpanStyle(color = linkColor, textDecoration = TextDecoration.Underline), val styles = TextLinkStyles(
) style = SpanStyle(color = linkColor, textDecoration = TextDecoration.Underline),
buildAnnotatedString { )
append(text) buildAnnotatedString {
for (match in regex.findAll(text)) { append(text)
// Trim trailing punctuation that commonly abuts a URL in prose. for (link in findWebLinks(text)) {
val raw = match.value addLink(
val url = raw.trimEnd('.', ',', ';', ':', '!', '?', ')', ']', '"', '\'') LinkAnnotation.Url(link.url, styles) { openWebLink(context, link.url) },
val end = match.range.first + url.length link.start,
addLink(LinkAnnotation.Url(url, styles), match.range.first, end) link.end,
)
}
} }
} }
} }
@@ -915,21 +918,19 @@ private fun formatWhen(
private fun Instant.toJavaLocalDateTime(zid: ZoneId): java.time.LocalDateTime = private fun Instant.toJavaLocalDateTime(zid: ZoneId): java.time.LocalDateTime =
java.time.LocalDateTime.ofInstant(java.time.Instant.ofEpochMilli(toEpochMilliseconds()), zid) java.time.LocalDateTime.ofInstant(java.time.Instant.ofEpochMilli(toEpochMilliseconds()), zid)
/** Open [url] in a browsable app, or say so when none can take it. */
private fun openWebLink(context: Context, url: String) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)).addCategory(Intent.CATEGORY_BROWSABLE)
if (runCatching { context.startActivity(intent) }.isFailure) {
Toast.makeText(context, R.string.link_open_failed, Toast.LENGTH_SHORT).show()
}
}
/** Open a maps intent for [query]; fall back to a web maps URL if no app handles geo:. */ /** Open a maps intent for [query]; fall back to a web maps URL if no app handles geo:. */
private fun openInMaps(context: Context, query: String) { private fun openInMaps(context: Context, query: String) {
val encoded = Uri.encode(query) val encoded = Uri.encode(query)
val geo = Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q=$encoded")) val geo = Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q=$encoded"))
try { if (runCatching { context.startActivity(geo) }.isFailure) {
context.startActivity(geo) openWebLink(context, "https://www.google.com/maps/search/?api=1&query=$encoded")
} catch (e: ActivityNotFoundException) {
val web = Intent(
Intent.ACTION_VIEW,
Uri.parse("https://www.google.com/maps/search/?api=1&query=$encoded"),
)
try {
context.startActivity(web)
} catch (e2: ActivityNotFoundException) {
// No browser either — nothing sensible to do; swallow.
}
} }
} }
@@ -0,0 +1,18 @@
package de.jeanlucmakiola.calendula.ui.detail
/** An http(s) URL found in free text, spanning [start] until [end] (exclusive). */
internal data class WebLink(val start: Int, val end: Int, val url: String)
private val webLinkRegex = Regex("""https?://[^\s<>"]+""", RegexOption.IGNORE_CASE)
/**
* Find the http(s) URLs in [text]. Trailing prose punctuation is left out of
* each match, and the scheme is lower-cased so intent filters match it.
*/
internal fun findWebLinks(text: String): List<WebLink> = webLinkRegex.findAll(text).mapNotNull { match ->
val raw = match.value.trimEnd('.', ',', ';', ':', '!', '?', ')', ']', '\'')
val schemeEnd = raw.indexOf(':')
if (raw.length <= schemeEnd + 3) return@mapNotNull null
val url = raw.substring(0, schemeEnd).lowercase() + raw.substring(schemeEnd)
WebLink(match.range.first, match.range.first + raw.length, url)
}.toList()
+2
View File
@@ -211,6 +211,8 @@
<string name="event_detail_calendar_unknown">Unknown calendar</string> <string name="event_detail_calendar_unknown">Unknown calendar</string>
<string name="event_detail_title">Title</string> <string name="event_detail_title">Title</string>
<string name="event_detail_location">Location</string> <string name="event_detail_location">Location</string>
<string name="event_detail_open_in_maps">Open in maps</string>
<string name="link_open_failed">No app can open this link</string>
<string name="event_detail_description">Description</string> <string name="event_detail_description">Description</string>
<string name="event_detail_attendees">Attendees</string> <string name="event_detail_attendees">Attendees</string>
<string name="event_detail_recurrence">Recurrence</string> <string name="event_detail_recurrence">Recurrence</string>
@@ -0,0 +1,52 @@
package de.jeanlucmakiola.calendula.ui.detail
import com.google.common.truth.Truth.assertThat
import org.junit.jupiter.api.Test
class WebLinksTest {
@Test
fun `a plain address has no links`() {
assertThat(findWebLinks("Office B, 12 Main St.")).isEmpty()
}
@Test
fun `a bare meeting link spans the whole text`() {
val text = "https://meet.google.com/abc-defg-hij"
assertThat(findWebLinks(text)).containsExactly(WebLink(0, text.length, text))
}
@Test
fun `a capitalised scheme is matched and lower-cased`() {
val links = findWebLinks("Https://zoom.us/j/123")
assertThat(links.single().url).isEqualTo("https://zoom.us/j/123")
assertThat(links.single().end).isEqualTo(21)
}
@Test
fun `angle brackets around a link stay outside it`() {
val text = "Microsoft Teams Meeting <https://teams.microsoft.com/l/meetup-join/x>"
val link = findWebLinks(text).single()
assertThat(link.url).isEqualTo("https://teams.microsoft.com/l/meetup-join/x")
assertThat(text.substring(link.start, link.end)).isEqualTo(link.url)
}
@Test
fun `trailing punctuation is left out of the link`() {
val link = findWebLinks("Office B (https://office.example.com).").single()
assertThat(link.url).isEqualTo("https://office.example.com")
}
@Test
fun `every link in the text is found`() {
val links = findWebLinks("Room 3 / https://zoom.us/j/1 / https://meet.google.com/x")
assertThat(links.map { it.url })
.containsExactly("https://zoom.us/j/1", "https://meet.google.com/x")
.inOrder()
}
@Test
fun `other schemes and a bare scheme are not links`() {
assertThat(findWebLinks("ftp://example.com mailto:a@b.c https://")).isEmpty()
}
}
+1 -1
View File
@@ -184,7 +184,7 @@ on every pull request:
| `images/icon.png` | 512×512, 32-bit PNG | | `images/icon.png` | 512×512, 32-bit PNG |
| `images/featureGraphic.png` | 1024×500, JPEG or 24-bit PNG | | `images/featureGraphic.png` | 1024×500, JPEG or 24-bit PNG |
| `images/*Screenshots/*` | JPEG or 24-bit PNG (no alpha), sides 320–3840, long edge ≤ 2× short, 2–8 per type | | `images/*Screenshots/*` | JPEG or 24-bit PNG (no alpha), sides 320–3840, long edge ≤ 2× short, 2–8 per type |
| locale directories | exactly the ones in `fastlane/store-locales.txt`, which maps every app `values-*` to a Play locale code | | locale directories | exactly the ones in `fastlane/store-locales.txt`, which maps every app `values-*` to a Play locale code; the code must be one Play accepts (`nl-NL`, not `nl`) |
A locale without its own images falls back to en-US in both stores, so graphics A locale without its own images falls back to en-US in both stores, so graphics
only need to exist there. Adding an app language means adding its line to only need to exist there. Adding an app language means adding its line to
@@ -0,0 +1,2 @@
إصلاحات
• النقر على رابط في موقع الحدث يفتحه الآن في المتصفح بدلًا من تطبيق الخرائط. النقر على العنوان ما زال يفتح الخرائط.
@@ -0,0 +1,7 @@
لم يصل الإصداران 2.22.0 و2.22.1 إلى Google Play، لذا هذا أول إصدار 2.22 هناك. التطبيق مطابق للإصدار 2.22.1.
• يتنقّل اليوم والأسبوع والشهر بمُنزلق يتبع إصبعك.
• يعرض العرض متعدد الأيام عدداً قابلاً للتخصيص من الأيام جنباً إلى جنب.
• الساعات المرئية: يملأ نطاق ساعات تختاره الشاشة.
• يبرز اليوم في شبكة الشهر.
• يُفتح الرابط في موقع الحدث في المتصفح.
@@ -0,0 +1 @@
عاد اسم صفحة المتجر إلى "Calendula: التقويم". لم يتغير شيء في التطبيق.
+1 -1
View File
@@ -1 +1 @@
Calendula Calendula: التقويم
@@ -0,0 +1,2 @@
Выпраўлена
• Націск на спасылку ў месцы падзеі адкрывае яе ў браўзеры, а не ў праграме карт. Націск на адрас па-ранейшаму адкрывае карты.
@@ -0,0 +1,7 @@
Вэрсіі 2.22.0 і 2.22.1 не трапілі ў Google Play, таму гэта першая вэрсія 2.22 там. Праграма такая ж, як 2.22.1.
• Дзень, Тыдзень і Месяц перагортваюцца пэйджарам, які сочыць за пальцам.
• Шматдзённы выгляд паказвае наладжвальную колькасць дзён побач.
• Бачныя гадзіны: абраны дыяпазон гадзін запаўняе экран.
• Сёньня вылучаецца ў сетцы месяца.
• Спасылка ў месцы падзеі адкрываецца ў браўзеры.
@@ -0,0 +1 @@
Старонка ў краме зноў называецца «Calendula: Каляндар». Праграма не змянілася.
+1 -1
View File
@@ -1 +1 @@
Calendula Calendula: Каляндар
@@ -0,0 +1,2 @@
Opraveno
• Klepnutí na odkaz v místě události ho otevře v prohlížeči místo v mapách. Klepnutí na adresu dál otevírá mapy.
@@ -0,0 +1,7 @@
Verze 2.22.0 a 2.22.1 se na Google Play nedostaly, takže tohle je tam první verze 2.22. Aplikace je stejná jako 2.22.1.
• Den, Týden a Měsíc listují stránkovačem, který sleduje prst.
• Vícedenní zobrazení ukazuje nastavitelný počet dní vedle sebe.
• Viditelné hodiny: zvolený rozsah hodin vyplní obrazovku.
• Dnes vyniká v mřížce měsíce.
• Odkaz v místě události se otevře v prohlížeči.
@@ -0,0 +1 @@
Stránka v obchodě se opět jmenuje „Calendula: Kalendář“. Aplikace se nezměnila.
+1 -1
View File
@@ -1 +1 @@
Calendula Calendula: Kalendář
@@ -0,0 +1,2 @@
Behoben
• Ein Tipp auf einen Link im Ort eines Termins öffnet ihn im Browser statt in einer Karten-App. Ein Tipp auf die Adresse öffnet weiterhin die Karte.
@@ -0,0 +1,7 @@
Google Play hat 2.22.0 und 2.22.1 verpasst, deshalb ist das dort die erste 2.22-Version. Die App ist dieselbe wie 2.22.1.
• Tag, Woche und Monat lassen sich mit einem fingerfolgenden Pager wischen.
• Mehrtagesansicht: einstellbare Anzahl Tage nebeneinander.
• Sichtbare Stunden: ein gewählter Stundenbereich füllt den Bildschirm.
• Heute hebt sich im Monatsraster ab.
• Ein Link im Ort eines Termins öffnet sich im Browser.
@@ -0,0 +1 @@
Der Store-Eintrag heißt wieder „Calendula: Kalender“. An der App hat sich nichts geändert.
+1 -1
View File
@@ -1 +1 @@
Calendula Calendula: Kalender
@@ -0,0 +1,2 @@
Fixed
• Tapping a link in an event's location opens it in the browser instead of a maps app. Tapping the address still opens maps.
@@ -0,0 +1,7 @@
Google Play missed 2.22.0 and 2.22.1, so this is the first 2.22 release there. The app is the same as 2.22.1.
• Day, Week and Month follow your finger when you swipe between dates.
• A multi-day view shows a set number of days side by side.
• Visible hours fits the hours you choose to the screen.
• Today stands out in the month grid.
• A link in an event's location opens in the browser.
@@ -0,0 +1 @@
The store listing is called "Calendula: Calendar" again. Nothing in the app changed.
+1 -1
View File
@@ -1 +1 @@
Calendula Calendula: Calendar
@@ -0,0 +1,2 @@
Corregido
• Al tocar un enlace en la ubicación de un evento, se abre en el navegador en lugar de en una app de mapas. Tocar la dirección sigue abriendo los mapas.
@@ -0,0 +1,7 @@
2.22.0 y 2.22.1 no llegaron a Google Play, así que esta es la primera versión 2.22 allí. La app es la misma que 2.22.1.
• Día, Semana y Mes se deslizan con un paginador que sigue tu dedo.
• Vista de varios días: muestra un número configurable de días uno junto a otro.
• Horas visibles: un rango de horas elegido llena la pantalla.
• Hoy destaca en la cuadrícula del mes.
• Un enlace en la ubicación de un evento se abre en el navegador.
@@ -0,0 +1 @@
La ficha de la tienda vuelve a llamarse «Calendula: Calendario». La app no cambia.
+1 -1
View File
@@ -1 +1 @@
Calendula Calendula: Calendario
@@ -0,0 +1,2 @@
Corrigé
• Toucher un lien dans le lieu d'un événement l'ouvre dans le navigateur et non plus dans une app de cartes. Toucher l'adresse ouvre toujours les cartes.
@@ -0,0 +1,7 @@
Les versions 2.22.0 et 2.22.1 ne sont pas arrivées sur Google Play ; voici donc la première version 2.22 sur Play. L'app est identique à la 2.22.1.
• Jour, Semaine et Mois défilent avec un pager qui suit le doigt.
• Vue multi-jours : affiche un nombre de jours réglable, côte à côte.
• Heures visibles : une plage d'heures choisie remplit l'écran.
• Aujourd'hui ressort dans la grille du mois.
• Un lien dans le lieu d'un événement s'ouvre dans le navigateur.
@@ -0,0 +1 @@
La fiche du store s'appelle de nouveau « Calendula: Calendrier ». L'app ne change pas.
+1 -1
View File
@@ -1 +1 @@
Calendula Calendula: Calendrier
@@ -0,0 +1,2 @@
Javítva
• Az esemény helyszínében lévő linkre koppintva az a böngészőben nyílik meg térképalkalmazás helyett. A címre koppintva továbbra is a térkép nyílik meg.
@@ -0,0 +1,7 @@
A 2.22.0 és a 2.22.1 nem jutott el a Google Playre, így ez az első 2.22-es verzió ott. Az alkalmazás ugyanaz, mint a 2.22.1.
• A Nap, Hét és Hónap nézet ujjkövető lapozóval lapozható.
• A többnapos nézet beállítható számú napot jelenít meg egymás mellett.
• Látható órák: a kiválasztott óratartomány kitölti a képernyőt.
• A mai nap kiemelkedik a havi rácsban.
• Az esemény helyszínében lévő link a böngészőben nyílik meg.
@@ -0,0 +1 @@
Az áruházi oldal neve ismét „Calendula: Naptár”. Az alkalmazás nem változott.
+1 -1
View File
@@ -1 +1 @@
Calendula Calendula: Naptár
@@ -0,0 +1,2 @@
Corretto
• Toccare un link nel luogo di un evento lo apre nel browser invece che in un'app di mappe. Toccare l'indirizzo apre ancora le mappe.
@@ -0,0 +1,7 @@
Le versioni 2.22.0 e 2.22.1 non sono arrivate su Google Play, quindi questa è la prima versione 2.22 lì. L'app è la stessa della 2.22.1.
• Giorno, Settimana e Mese scorrono con un pager che segue il dito.
• Vista multi-giorno: mostra un numero configurabile di giorni affiancati.
• Ore visibili: un intervallo di ore scelto riempie lo schermo.
• Oggi risalta nella griglia del mese.
• Un link nel luogo di un evento si apre nel browser.
@@ -0,0 +1 @@
La scheda dello store si chiama di nuovo «Calendula: Calendario». L'app non cambia.
+1 -1
View File
@@ -1 +1 @@
Calendula Calendula: Calendario
@@ -0,0 +1,2 @@
修正
• 予定の場所にあるリンクをタップすると、地図アプリではなくブラウザで開くようになりました。住所をタップすると引き続き地図が開きます。
@@ -0,0 +1,7 @@
2.22.0と2.22.1はGoogle Playに配信されなかったため、これがGoogle Playでの最初の2.22です。アプリの内容は2.22.1と同じです。
• 日・週・月ビューが指に追従するページャーでめくれます。
• マルチデイビューで、設定可能な日数を横に並べて表示します。
• 表示時間帯: 選んだ時間の範囲が画面いっぱいに表示されます。
• 月表示で今日が目立ちます。
• 予定の場所にあるリンクはブラウザで開きます。
@@ -0,0 +1 @@
ストアの掲載名が再び「Calendula: カレンダー」になりました。アプリ自体に変更はありません。
+1 -1
View File
@@ -1 +1 @@
Calendula Calendula: カレンダー
@@ -0,0 +1,2 @@
Opgelost
• Tikken op een link in de locatie van een afspraak opent die in de browser in plaats van in een kaarten-app. Tikken op het adres opent nog steeds de kaart.
@@ -0,0 +1,7 @@
2.22.0 en 2.22.1 zijn nooit op Google Play verschenen, dus dit is daar de eerste 2.22-versie. De app is gelijk aan 2.22.1.
• Dag, Week en Maand blader je door met een pager die je vinger volgt.
• Een meerdaagse weergave toont een instelbaar aantal dagen naast elkaar.
• Zichtbare uren: een gekozen tijdsbereik vult het scherm.
• Vandaag valt op in het maandraster.
• Een link in de locatie van een afspraak opent in de browser.
@@ -0,0 +1 @@
De winkelvermelding heet weer "Calendula: Agenda". Aan de app is niets veranderd.
@@ -0,0 +1 @@
Calendula: Agenda
-1
View File
@@ -1 +0,0 @@
Calendula
@@ -0,0 +1,2 @@
Poprawki
• Dotknięcie linku w miejscu wydarzenia otwiera go w przeglądarce zamiast w aplikacji map. Dotknięcie adresu nadal otwiera mapy.
@@ -0,0 +1,7 @@
Wersje 2.22.0 i 2.22.1 nie trafiły do Google Play, więc to pierwsza wersja 2.22 w tym sklepie. Aplikacja jest taka sama jak 2.22.1.
• Dzień, Tydzień i Miesiąc przewijają się pagerem, który podąża za palcem.
• Widok wielodniowy pokazuje ustawialną liczbę dni obok siebie.
• Widoczne godziny: wybrany zakres godzin wypełnia ekran.
• Dziś wyróżnia się w siatce miesiąca.
• Link w miejscu wydarzenia otwiera się w przeglądarce.
@@ -0,0 +1 @@
Strona w sklepie znów nazywa się „Calendula: Kalendarz”. Aplikacja się nie zmieniła.
+1 -1
View File
@@ -1 +1 @@
Calendula Calendula: Kalendarz
@@ -0,0 +1,2 @@
Corrigido
• Tocar em um link no local de um evento agora o abre no navegador em vez de em um app de mapas. Tocar no endereço continua abrindo os mapas.
@@ -0,0 +1,7 @@
As versões 2.22.0 e 2.22.1 não chegaram ao Google Play, então esta é a primeira versão 2.22 lá. O app é o mesmo da 2.22.1.
• Dia, Semana e Mês avançam com um pager que acompanha o dedo.
• Visualização de vários dias: mostra um número configurável de dias lado a lado.
• Horas visíveis: um intervalo de horas escolhido preenche a tela.
• Hoje se destaca na grade do mês.
• Um link no local de um evento abre no navegador.
@@ -0,0 +1 @@
A página da loja voltou a se chamar "Calendula: Calendário". O app não mudou.
+1 -1
View File
@@ -1 +1 @@
Calendula Calendula: Calendário
@@ -0,0 +1,2 @@
Corrigido
• Tocar numa ligação no local de um evento abre-a no navegador em vez de numa app de mapas. Tocar na morada continua a abrir os mapas.
@@ -0,0 +1,7 @@
As versões 2.22.0 e 2.22.1 não chegaram ao Google Play, por isso esta é a primeira versão 2.22 lá. A app é a mesma da 2.22.1.
• Dia, Semana e Mês deslizam com um pager que acompanha o dedo.
• Vista de vários dias: mostra um número configurável de dias lado a lado.
• Horas visíveis: um intervalo de horas escolhido preenche o ecrã.
• Hoje destaca-se na grelha do mês.
• Uma ligação no local de um evento abre no navegador.
@@ -0,0 +1 @@
A página da loja volta a chamar-se "Calendula: Calendário". A app não mudou.
+1 -1
View File
@@ -1 +1 @@
Calendula Calendula: Calendário
@@ -0,0 +1,2 @@
Исправлено
• Нажатие на ссылку в месте события открывает её в браузере, а не в приложении карт. Нажатие на адрес по-прежнему открывает карты.
@@ -0,0 +1,7 @@
Версии 2.22.0 и 2.22.1 не попали в Google Play, поэтому это первая версия 2.22 там. Приложение то же, что и 2.22.1.
• День, Неделя и Месяц листаются пейджером, который следует за пальцем.
• Многодневный вид показывает настраиваемое число дней рядом друг с другом.
• Видимые часы: выбранный диапазон часов заполняет экран.
• Сегодня выделяется в сетке месяца.
• Ссылка в месте события открывается в браузере.
@@ -0,0 +1 @@
Страница в магазине снова называется «Calendula: Календарь». Приложение не изменилось.
+1 -1
View File
@@ -1 +1 @@
Calendula Calendula: Календарь
@@ -0,0 +1,2 @@
Opravené
• Ťuknutie na odkaz v mieste udalosti ho otvorí v prehliadači namiesto v mapách. Ťuknutie na adresu naďalej otvára mapy.
@@ -0,0 +1,7 @@
Verzie 2.22.0 a 2.22.1 sa na Google Play nedostali, takže toto je tam prvá verzia 2.22. Aplikácia je rovnaká ako 2.22.1.
• Deň, Týždeň a Mesiac sa listujú stránkovačom, ktorý sleduje prst.
• Viacdňové zobrazenie ukazuje nastaviteľný počet dní vedľa seba.
• Viditeľné hodiny: zvolený rozsah hodín vyplní obrazovku.
• Dnešok vyniká v mriežke mesiaca.
• Odkaz v mieste udalosti sa otvorí v prehliadači.
@@ -0,0 +1 @@
Stránka v obchode sa opäť volá „Calendula: Kalendár“. Aplikácia sa nezmenila.
+1 -1
View File
@@ -1 +1 @@
Calendula Calendula: Kalendár
@@ -0,0 +1,2 @@
修复
• 点按日程地点中的链接现在会在浏览器中打开,而不是地图应用。点按地址仍会打开地图。
@@ -0,0 +1,7 @@
2.22.0 和 2.22.1 未能发布到 Google Play,因此这是 Google Play 上的第一个 2.22 版本。应用内容与 2.22.1 相同。
• 日、周、月视图可以用跟手的分页手势滑动切换。
• 多日视图并排显示可自定义天数。
• 可见时段:选定的时间范围会铺满整个屏幕。
• “今天”在月视图网格中突出显示。
• 日程地点中的链接会在浏览器中打开。
@@ -0,0 +1 @@
商店页面名称恢复为“Calendula: 日历”。应用本身没有变化。
+1 -1
View File
@@ -1 +1 @@
Calendula Calendula: 日历
+1 -1
View File
@@ -12,7 +12,7 @@ fr fr-FR
hu hu-HU hu hu-HU
it it-IT it it-IT
ja ja-JP ja ja-JP
nl nl nl nl-NL
pl pl-PL pl pl-PL
pt pt-PT pt pt-PT
pt-rBR pt-BR pt-rBR pt-BR
+15
View File
@@ -7,6 +7,7 @@ fail the upload after the release has shipped everywhere else.
- every locale directory is listed in fastlane/store-locales.txt, and every - every locale directory is listed in fastlane/store-locales.txt, and every
app language (res/values-*) has an entry there and a directory app language (res/values-*) has an entry there and a directory
- every store code is a language Play accepts (supply's ALL_LANGUAGES)
- title / short / full description exist, are non-empty and within Play's caps, - title / short / full description exist, are non-empty and within Play's caps,
and the full description isn't hard-wrapped and the full description isn't hard-wrapped
- icon: 512x512 32-bit PNG; featureGraphic: 1024x500 JPEG or 24-bit PNG - icon: 512x512 32-bit PNG; featureGraphic: 1024x500 JPEG or 24-bit PNG
@@ -29,6 +30,16 @@ SCREENSHOT_DIRS = {"phoneScreenshots", "sevenInchScreenshots", "tenInchScreensho
"tvScreenshots", "wearScreenshots"} "tvScreenshots", "wearScreenshots"}
IMAGE_EXTS = {".png", ".jpg", ".jpeg"} IMAGE_EXTS = {".png", ".jpg", ".jpeg"}
# fastlane supply/lib/supply/languages.rb, with `_` back to `-`.
PLAY_LOCALES = set("""
af am ar az-AZ be bg bn-BD ca cs-CZ da-DK de-DE el-GR en-AU en-CA en-GB en-IN
en-SG en-US en-ZA es-419 es-ES es-US et eu-ES fa fi-FI fil fr-CA fr-FR gl-ES
hi-IN hr hu-HU hy-AM id is-IS it-IT iw-IL ja-JP ka-GE km-KH kn-IN ko-KR ky-KG
lo-LA lt lv mk-MK ml-IN mn-MN mr-IN ms ms-MY my-MM ne-NP nl-NL no-NO pl-PL
pt-BR pt-PT rm ro ru-RU si-LK sk sl sr sv-SE sw ta-IN te-IN th tr-TR uk vi
zh-CN zh-HK zh-TW zu
""".split())
errors = [] errors = []
@@ -80,6 +91,10 @@ def check_mapping():
for q in sorted(mapping.keys() - app_langs): for q in sorted(mapping.keys() - app_langs):
error(f"{rel(MAPPING)} maps '{q}' but the app has no values-{q}") error(f"{rel(MAPPING)} maps '{q}' but the app has no values-{q}")
for q, store in sorted(mapping.items()):
if store not in PLAY_LOCALES:
error(f"{rel(MAPPING)} maps '{q}' to '{store}', which Play doesn't accept as a listing language")
stores = set(mapping.values()) stores = set(mapping.values())
dirs = {d.name for d in META.iterdir() if d.is_dir()} dirs = {d.name for d in META.iterdir() if d.is_dir()}
for d in sorted(dirs - stores): for d in sorted(dirs - stores):