diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 0496e384a..542397df5 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -118,12 +118,19 @@ jobs:
# Keyed on the lockfile, so it is reused until a dependency actually
# moves. Without it every release re-downloads the full package set —
# mise caches the SDK but knows nothing about pub.
+ #
+ # No restore-keys fallback: `~/.pub-cache/git` mirrors the exact fork
+ # commit the lockfile resolved, and a lockfile bump (e.g. a new MapLibre
+ # fork pin) must not reuse a mirror of the previous commit — pub then
+ # resolves the old fork's dependency set and "removes" packages the new
+ # lockfile still needs, corrupting .dart_tool/package_graph.json. A
+ # precise key costs one full download on a dependency change and is
+ # correct every time.
- name: Cache pub packages
uses: actions/cache@v4
with:
path: ~/.pub-cache
key: ${{ runner.os }}-pub-${{ hashFiles('pubspec.lock') }}
- restore-keys: ${{ runner.os }}-pub-
# The iOS build resolves its dependencies through Swift Package Manager
# (there is no Podfile). Uncached, every release re-clones and rebuilds
diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts
index 78f72ec6c..1cc1be24d 100644
--- a/android/app/build.gradle.kts
+++ b/android/app/build.gradle.kts
@@ -130,7 +130,11 @@ dependencies {
// put it on a consumer's compile classpath, so calling addListener/get needs
// this explicitly.
implementation("androidx.concurrent:concurrent-futures:1.2.0")
+ // Durable, queryable watchdog behind the geofence/alarm background-location
+ // path. WorkManager persists its unique periodic work across process death
+ // and reboot; it only repairs an overdue path and never takes a healthy
+ // path's extra location fix.
+ implementation("androidx.work:work-runtime:2.11.2")
// Backports java.time/etc. for awesome_notifications (see compileOptions).
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5")
}
-
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index f92c76c8b..0d090c186 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -10,9 +10,8 @@
-
+
@@ -65,16 +64,20 @@
-
+
-
+
+
+
result.success(status())
+ "openSystemSettings" -> result.success(openAppDetails())
"openOemSettings" -> result.success(openOemSettings())
else -> result.notImplemented()
}
@@ -368,6 +369,16 @@ class BackgroundExecutionChannel(private val context: Context) :
Log.i(TAG, "vendor screen $screen unavailable", e)
}
}
+ return openAppDetails()
+ }
+
+ /**
+ * The standard Android restriction and an OEM's auto-start manager are two
+ * different controls. This destination deliberately skips the OEM chain so
+ * a user fixing Android's own "Restricted" state lands on DPIP's app page,
+ * not on (for example) Samsung's sleeping-app list.
+ */
+ private fun openAppDetails(): String {
return try {
context.startActivity(
Intent(
diff --git a/android/app/src/main/kotlin/com/exptech/dpip/BackgroundLocationChannel.kt b/android/app/src/main/kotlin/com/exptech/dpip/BackgroundLocationChannel.kt
index 08d3000de..3b195406d 100644
--- a/android/app/src/main/kotlin/com/exptech/dpip/BackgroundLocationChannel.kt
+++ b/android/app/src/main/kotlin/com/exptech/dpip/BackgroundLocationChannel.kt
@@ -6,7 +6,6 @@ import android.content.pm.PackageManager
import android.os.Build
import android.os.Handler
import android.os.Looper
-import android.util.Log
import androidx.core.content.ContextCompat
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
@@ -15,10 +14,9 @@ import io.flutter.plugin.common.MethodChannel
* Starts/stops autonomous background device-location reporting — the Android
* counterpart of iOS `BackgroundLocationPlugin`.
*
- * Primary spine (with Google Play services): a low-power, event-driven,
- * OEM-kill-resistant **EXIT geofence** ([GeofenceManager]) — an initial fix is
- * taken and a geofence armed around it; the OS reports only real moves. Fallback
- * (de-Googled devices): the adaptive-interval alarm ([LocationAlarmScheduler]).
+ * Fast path (with Google Play services): a low-power **EXIT geofence**. An
+ * independent 10–30 minute alarm remains behind it on every Android device and
+ * repairs silent geofence loss. Long work runs in [BackgroundLocationJobService].
* The foreground `DeviceLocationReporter` covers the app-open case; this is the
* terminated/background safety net.
*/
@@ -27,7 +25,6 @@ class BackgroundLocationChannel(private val context: Context) :
companion object {
const val NAME = "com.exptech.dpip/background_location"
- private const val TAG = "DpipBgLocation"
}
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
@@ -40,42 +37,36 @@ class BackgroundLocationChannel(private val context: Context) :
result.error("bad_args", "Missing start args", null)
return
}
- BgLocationStore.saveConfig(context, token, version, platform)
- BgLocationStore.note(
- context,
- "start: gms=${GmsAvailability.available(context)} " +
- "bgPermission=${GeofenceManager.hasPermission(context)}",
+ val wasEnabled = BgLocationStore.enabled(context)
+ val sameConfig = BgLocationStore.configMatches(
+ context, token, version, platform,
)
- if (GmsAvailability.available(context)) {
- // The alarm is NOT cancelled here. Arming the geofence needs
- // a fix, and getting one can fail — location off at that
- // moment, a 15 s BALANCED timeout indoors, no fresh cached
- // fix. Cancelling first meant a failed arm left the device
- // with neither spine and nothing scheduled to retry, so
- // background reporting silently stopped until the next time
- // the user opened the app. [armGeofence] stands the alarm
- // down only once Play services confirms a fence is live.
- //
- // Schedule before arming, not after. Arming waits on a fix
- // (up to ~20 s) and then on an asynchronous registration,
- // and on a first-ever enable — or any stop/start from the
- // developer page, which cancels the alarm — there is nothing
- // pending for that whole window. A process death inside it
- // left reporting enabled with no fence and no alarm, and
- // nothing that would ever notice.
- LocationAlarmScheduler.ensure(context)
- armGeofence(context.applicationContext)
- } else {
- GeofenceManager.remove(context)
- BgLocationStore.prefs(context).edit()
- .putLong(
- BgLocationStore.KEY_INTERVAL_MIN,
- LocationAlarmScheduler.DEFAULT_INTERVAL_MIN,
- )
- .apply()
- LocationAlarmScheduler.schedule(
- context, LocationAlarmScheduler.DEFAULT_INTERVAL_MIN,
+ val hadPermission = BgLocationStore.permissionReady(context)
+ val hasPermission = GeofenceManager.hasPermission(context)
+
+ if (!sameConfig) BgLocationStore.saveConfig(context, token, version, platform)
+ BgLocationStore.setPermissionReady(context, hasPermission)
+ LocationAlarmScheduler.ensure(context)
+ BackgroundLocationWatchdog.ensure(context)
+
+ // An unchanged start preserves both scheduler deadlines and does
+ // no location work. Flutter calls this on resume; re-registering
+ // the fence and taking a fix there caused the foreground wake storm.
+ val reason = when {
+ !sameConfig && !wasEnabled -> BackgroundLocationJobService.REASON_START
+ hasPermission && !hadPermission ->
+ BackgroundLocationJobService.REASON_PERMISSION_RESTORED
+ !sameConfig -> BackgroundLocationJobService.REASON_CONFIG
+ else -> null
+ }
+ if (!hasPermission) {
+ BgLocationStore.setArmed(context, false)
+ } else if (reason != null) {
+ BgLocationStore.note(
+ context,
+ "start: $reason gms=${GmsAvailability.available(context)}",
)
+ BackgroundLocationJobService.enqueue(context, reason)
}
result.success(null)
}
@@ -84,10 +75,17 @@ class BackgroundLocationChannel(private val context: Context) :
BgLocationStore.disable(context)
GeofenceManager.remove(context)
LocationAlarmScheduler.cancel(context)
+ BackgroundLocationWatchdog.cancel(context)
+ BackgroundLocationJobService.cancel(context)
result.success(null)
}
- "diagnostics" -> result.success(diagnostics())
+ // WorkManager exposes real work state asynchronously. Query it off
+ // the platform thread so opening Developer diagnostics cannot stall UI.
+ "diagnostics" -> Thread {
+ val snapshot = diagnostics()
+ Handler(Looper.getMainLooper()).post { result.success(snapshot) }
+ }.start()
// Everything the background path recorded since the last drain, so
// it can be written into the app's own log. A BroadcastReceiver has
@@ -122,55 +120,13 @@ class BackgroundLocationChannel(private val context: Context) :
}
}
- // Take an initial fix off the main thread, arm the geofence around it, and
- // report it.
- //
- // Every path out of here leaves exactly one spine armed. The geofence is the
- // one worth having — Play services keeps monitoring it after an OEM battery
- // manager kills our process — but it can only be armed from a fix we do not
- // always get, and `addGeofences` can still refuse afterwards. So the alarm
- // stays scheduled until the fence is confirmed live, and is (re)scheduled if
- // it is not. Both running briefly is harmless: the report is an idempotent
- // GET, and the next successful arm cancels the alarm.
- private fun armGeofence(appContext: Context) {
- Thread {
- try {
- val location = FusedFix.get(appContext)
- if (location == null) {
- Log.w(TAG, "no fix available — geofence not armed, keeping the alarm")
- BgLocationStore.note(appContext, "arm: no fix, alarm only")
- LocationAlarmScheduler.ensure(appContext)
- return@Thread
- }
- if (!BgLocationStore.enabled(appContext)) return@Thread
- // Arm the fence first (spine safety), then report.
- GeofenceManager.register(appContext, location.latitude, location.longitude) { armed ->
- if (armed) {
- BgLocationStore.note(appContext, "arm: geofence live")
- LocationAlarmScheduler.resetWatchdog(appContext)
- } else {
- Log.w(TAG, "geofence refused — falling back to the alarm")
- BgLocationStore.note(appContext, "arm: geofence refused, alarm only")
- LocationAlarmScheduler.ensure(appContext)
- }
- }
- BgLocationStore.report(appContext, location.latitude, location.longitude)
- } catch (e: Exception) {
- Log.w(TAG, "background location arm failed", e)
- BgLocationStore.note(appContext, "arm failed: ${e.javaClass.simpleName}: ${e.message}")
- LocationAlarmScheduler.ensure(appContext)
- }
- }.start()
- }
-
/**
* A snapshot of whether background reporting is actually working, for the
* developer page. Keys are shared with the iOS plugin so one UI renders both.
*
- * `armed` is the honest answer to "is anything monitoring right now", which
- * is the question a user's bug report needs and the one nothing here could
- * previously answer: the Geofencing API cannot be queried, so it is tracked
- * as state; the alarm can be, via a no-create PendingIntent probe.
+ * The Geofencing API and AlarmManager expose no query for live registrations,
+ * so diagnostics report the last accepted registration/scheduling calls and
+ * the independent delivery/HTTP evidence beside them.
*/
private fun diagnostics(): Map {
val prefs = BgLocationStore.prefs(context)
@@ -185,7 +141,28 @@ class BackgroundLocationChannel(private val context: Context) :
val canFix = GeofenceManager.hasPermission(context)
val fenceArmed = BgLocationStore.armed(context) && canFix
val alarmArmed = LocationAlarmScheduler.isScheduled(context) && canFix
- val lastReportAt = prefs.getLong(BgLocationStore.KEY_LAST_REPORT_AT, 0L)
+ val legacyAttemptAt = prefs.getLong(BgLocationStore.KEY_LEGACY_LAST_REPORT_AT, 0L)
+ val attemptAt = prefs.getLong(BgLocationStore.KEY_LAST_ATTEMPT_AT, legacyAttemptAt)
+ val legacyAttemptOk = prefs.getBoolean(BgLocationStore.KEY_LEGACY_LAST_REPORT_OK, false)
+ val attemptOk = if (prefs.contains(BgLocationStore.KEY_LAST_ATTEMPT_OK)) {
+ prefs.getBoolean(BgLocationStore.KEY_LAST_ATTEMPT_OK, false)
+ } else {
+ legacyAttemptOk
+ }
+ val legacyAttemptCode = prefs.getInt(BgLocationStore.KEY_LEGACY_LAST_REPORT_CODE, -1)
+ val attemptCode = if (prefs.contains(BgLocationStore.KEY_LAST_ATTEMPT_CODE)) {
+ prefs.getInt(BgLocationStore.KEY_LAST_ATTEMPT_CODE, -1)
+ } else {
+ legacyAttemptCode
+ }
+ val successAt = prefs.getLong(
+ BgLocationStore.KEY_LAST_SUCCESS_AT,
+ if (legacyAttemptOk) legacyAttemptAt else 0L,
+ )
+ val successCode = prefs.getInt(
+ BgLocationStore.KEY_LAST_SUCCESS_CODE,
+ if (legacyAttemptOk) legacyAttemptCode else 0,
+ )
return mapOf(
"enabled" to BgLocationStore.enabled(context),
"authorization" to authorization(),
@@ -202,18 +179,21 @@ class BackgroundLocationChannel(private val context: Context) :
"wakeGeofence" to prefs.getInt("wake_geofence_n", 0),
"wakeAlarm" to prefs.getInt("wake_alarm_n", 0),
"wakeBoot" to prefs.getInt("wake_boot_n", 0),
- "lastGeofenceError" to (
- prefs.getInt("last_geofence_error", 0).takeIf { it != 0 }
- ),
- "lastReportAt" to (if (lastReportAt == 0L) null else lastReportAt),
- "lastReportOk" to (
- if (lastReportAt == 0L) null
- else prefs.getBoolean(BgLocationStore.KEY_LAST_REPORT_OK, false)
- ),
- "lastReportCode" to (
- if (lastReportAt == 0L) null
- else prefs.getInt(BgLocationStore.KEY_LAST_REPORT_CODE, -1)
- ),
+ "lastGeofenceError" to prefs.getInt("last_geofence_error", 0)
+ .takeIf { it != 0 }
+ ?.toString(),
+ "lastGeofenceTransitionAt" to prefs
+ .getLong("last_geofence_transition_at", 0L)
+ .takeIf { it > 0L },
+ "lastAttemptAt" to attemptAt.takeIf { it > 0L },
+ "lastAttemptOk" to attemptOk.takeIf { attemptAt > 0L },
+ "lastAttemptCode" to attemptCode.takeIf { attemptAt > 0L },
+ "lastSuccessAt" to successAt.takeIf { it > 0L },
+ "lastSuccessCode" to successCode.takeIf { successAt > 0L },
+ "lastThrottledAt" to prefs.getLong(BgLocationStore.KEY_LAST_THROTTLED_AT, 0L)
+ .takeIf { it > 0L },
+ "throttledCount" to prefs.getInt(BgLocationStore.KEY_THROTTLED_N, 0),
+ "nextAlarmAt" to LocationAlarmScheduler.nextWallTime(context),
"centreLat" to (
if (BgLocationStore.hasLast(context)) BgLocationStore.lastLat(context) else null
),
@@ -225,19 +205,14 @@ class BackgroundLocationChannel(private val context: Context) :
append(", geofence ").append(if (fenceArmed) "armed" else "not armed")
append(", alarm ")
if (alarmArmed) {
- append("scheduled every ")
- .append(
- prefs.getLong(
- BgLocationStore.KEY_INTERVAL_MIN,
- LocationAlarmScheduler.DEFAULT_INTERVAL_MIN,
- ),
- )
+ append("scheduled, adaptive ")
+ .append(LocationAlarmScheduler.storedInterval(context))
.append(" min")
} else {
append("not scheduled")
}
},
- )
+ ) + BackgroundLocationWatchdog.diagnostics(context)
}
/** The OS location authorization, in the same vocabulary the iOS side uses. */
diff --git a/android/app/src/main/kotlin/com/exptech/dpip/BackgroundLocationJobService.kt b/android/app/src/main/kotlin/com/exptech/dpip/BackgroundLocationJobService.kt
new file mode 100644
index 000000000..1524c606c
--- /dev/null
+++ b/android/app/src/main/kotlin/com/exptech/dpip/BackgroundLocationJobService.kt
@@ -0,0 +1,254 @@
+package com.exptech.dpip
+
+import android.app.job.JobInfo
+import android.app.job.JobParameters
+import android.app.job.JobScheduler
+import android.app.job.JobService
+import android.app.job.JobWorkItem
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.location.Location
+import android.os.Build
+import android.os.Handler
+import android.os.Looper
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.Executors
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.atomic.AtomicInteger
+
+/** Performs every long-running background-location operation outside receivers. */
+class BackgroundLocationJobService : JobService() {
+ companion object {
+ const val REASON_START = "start"
+ const val REASON_CONFIG = "config"
+ const val REASON_PERMISSION_RESTORED = "permission-restored"
+ const val REASON_ALARM = "alarm"
+ const val REASON_GEOFENCE_EXIT = "geofence-exit"
+ const val REASON_GEOFENCE_ERROR = "geofence-error"
+ const val REASON_BOOT = "boot"
+ const val REASON_WATCHDOG = "watchdog"
+
+ private const val JOB_ID = 888892
+ private const val EXTRA_REASON = "reason"
+ private const val EXTRA_HAS_LOCATION = "has_location"
+ private const val EXTRA_LAT = "lat"
+ private const val EXTRA_LNG = "lng"
+ private val executor = Executors.newSingleThreadExecutor()
+
+ /** Queues an event without starting location or network work in the caller. */
+ fun enqueue(context: Context, reason: String, location: Location? = null): Boolean {
+ val app = context.applicationContext
+ val intent = Intent()
+ .putExtra(EXTRA_REASON, reason)
+ .putExtra(EXTRA_HAS_LOCATION, location != null)
+ if (location != null) {
+ intent.putExtra(EXTRA_LAT, location.latitude)
+ intent.putExtra(EXTRA_LNG, location.longitude)
+ }
+ val scheduler = app.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
+ var accepted = submit(scheduler, jobInfo(app, expedited = true), intent, app)
+ if (!accepted && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ // Expedited quota is finite. A failed expedited enqueue must not
+ // lose the event; fall back to the immediate regular-job path.
+ accepted = submit(scheduler, jobInfo(app, expedited = false), intent, app)
+ }
+ if (!accepted) {
+ BgLocationStore.note(app, "job enqueue failed: $reason")
+ }
+ return accepted
+ }
+
+ private fun jobInfo(context: Context, expedited: Boolean): JobInfo {
+ val builder = JobInfo.Builder(
+ JOB_ID,
+ ComponentName(context, BackgroundLocationJobService::class.java),
+ )
+ if (expedited && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ builder.setExpedited(true)
+ } else {
+ // API 26–30 has no expedited jobs. A zero deadline is the
+ // platform-supported way to avoid batching urgent work there.
+ builder.setOverrideDeadline(0L)
+ }
+ return builder.build()
+ }
+
+ private fun submit(
+ scheduler: JobScheduler,
+ info: JobInfo,
+ intent: Intent,
+ context: Context,
+ ): Boolean = try {
+ scheduler.enqueue(info, JobWorkItem(intent)) == JobScheduler.RESULT_SUCCESS
+ } catch (error: RuntimeException) {
+ BgLocationStore.note(context, "job enqueue threw: ${error.javaClass.simpleName}")
+ false
+ }
+
+ fun cancel(context: Context) {
+ val scheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
+ scheduler.cancel(JOB_ID)
+ }
+ }
+
+ private val generation = AtomicInteger()
+ private val main = Handler(Looper.getMainLooper())
+
+ override fun onStartJob(params: JobParameters): Boolean {
+ val run = generation.incrementAndGet()
+ executor.execute { drain(params, run) }
+ return true
+ }
+
+ override fun onStopJob(params: JobParameters): Boolean {
+ generation.incrementAndGet()
+ // An incomplete JobWorkItem is redelivered when constraints allow.
+ return BgLocationStore.enabled(applicationContext)
+ }
+
+ private fun drain(params: JobParameters, run: Int) {
+ while (generation.get() == run) {
+ val item = params.dequeueWork() ?: break
+ try {
+ handle(item.intent)
+ } catch (error: Exception) {
+ BgLocationStore.note(
+ applicationContext,
+ "job failed: ${error.javaClass.simpleName}: ${error.message}",
+ )
+ }
+ if (generation.get() != run) return
+ params.completeWork(item)
+ }
+ if (generation.get() != run) return
+ main.post {
+ if (generation.get() == run) jobFinished(params, false)
+ }
+ }
+
+ private fun handle(intent: Intent) {
+ val app = applicationContext
+ if (!BgLocationStore.enabled(app)) return
+ val reason = intent.getStringExtra(EXTRA_REASON).orEmpty()
+ BgLocationStore.note(app, "job: $reason")
+
+ val permitted = GeofenceManager.hasPermission(app)
+ BgLocationStore.setPermissionReady(app, permitted)
+ if (!permitted) {
+ BgLocationStore.setArmed(app, false)
+ BgLocationStore.note(app, "job: background location unavailable")
+ if (reason == REASON_ALARM) scheduleAfterMissingFix(app)
+ return
+ }
+
+ val location = suppliedLocation(intent) ?: currentLocation(app)
+ if (!BgLocationStore.enabled(app)) return
+ val nextAlarm = if (reason == REASON_ALARM) {
+ val current = LocationAlarmScheduler.storedInterval(app)
+ val next = if (location == null) {
+ (current + 5).coerceAtMost(LocationAlarmScheduler.MAX_INTERVAL_MIN)
+ } else {
+ LocationAlarmScheduler.nextIntervalMinutes(
+ distanceFromLast(app, location),
+ current,
+ )
+ }
+ BgLocationStore.prefs(app).edit()
+ .putLong(BgLocationStore.KEY_INTERVAL_MIN, next)
+ .apply()
+ next
+ } else {
+ null
+ }
+
+ if (location != null) {
+ if (GmsAvailability.available(app)) {
+ registerAndWait(app, location.latitude, location.longitude)
+ } else {
+ BgLocationStore.setArmed(app, false)
+ BgLocationStore.saveLast(app, location.latitude, location.longitude)
+ }
+ if (!BgLocationStore.enabled(app)) return
+ BgLocationStore.report(app, location.latitude, location.longitude)
+ } else {
+ BgLocationStore.note(app, "job: no fix for $reason")
+ reRegisterLastCentre(app)
+ }
+
+ if (reason == REASON_ALARM && BgLocationStore.enabled(app)) {
+ LocationAlarmScheduler.schedule(
+ app,
+ nextAlarm ?: LocationAlarmScheduler.DEFAULT_INTERVAL_MIN,
+ )
+ }
+ }
+
+ private fun scheduleAfterMissingFix(context: Context) {
+ val next = (LocationAlarmScheduler.storedInterval(context) + 5)
+ .coerceAtMost(LocationAlarmScheduler.MAX_INTERVAL_MIN)
+ BgLocationStore.prefs(context).edit()
+ .putLong(BgLocationStore.KEY_INTERVAL_MIN, next)
+ .apply()
+ LocationAlarmScheduler.schedule(context, next)
+ }
+
+ private fun suppliedLocation(intent: Intent): Location? {
+ if (!intent.getBooleanExtra(EXTRA_HAS_LOCATION, false)) return null
+ return Location("geofence").apply {
+ latitude = intent.getDoubleExtra(EXTRA_LAT, 0.0)
+ longitude = intent.getDoubleExtra(EXTRA_LNG, 0.0)
+ }
+ }
+
+ private fun currentLocation(context: Context): Location? {
+ if (GmsAvailability.available(context)) {
+ try {
+ FusedFix.get(context)?.let { return it }
+ } catch (error: Exception) {
+ BgLocationStore.note(context, "fused fix failed: ${error.javaClass.simpleName}")
+ }
+ }
+ return LocationFetcher.getFix(context)
+ }
+
+ private fun registerAndWait(context: Context, lat: Double, lng: Double) {
+ val settled = CountDownLatch(1)
+ GeofenceManager.register(context, lat, lng) { armed ->
+ BgLocationStore.note(
+ context,
+ if (armed) {
+ "geofence registration accepted"
+ } else {
+ "geofence registration failed"
+ },
+ )
+ settled.countDown()
+ }
+ if (!settled.await(10, TimeUnit.SECONDS)) {
+ BgLocationStore.note(context, "geofence registration timed out")
+ }
+ }
+
+ private fun reRegisterLastCentre(context: Context) {
+ if (!GmsAvailability.available(context) || !BgLocationStore.hasLast(context)) return
+ registerAndWait(
+ context,
+ BgLocationStore.lastLat(context),
+ BgLocationStore.lastLng(context),
+ )
+ }
+
+ private fun distanceFromLast(context: Context, location: Location): Double? {
+ if (!BgLocationStore.hasLast(context)) return null
+ val results = FloatArray(1)
+ Location.distanceBetween(
+ BgLocationStore.lastLat(context),
+ BgLocationStore.lastLng(context),
+ location.latitude,
+ location.longitude,
+ results,
+ )
+ return results[0].toDouble()
+ }
+}
diff --git a/android/app/src/main/kotlin/com/exptech/dpip/BackgroundLocationWatchdog.kt b/android/app/src/main/kotlin/com/exptech/dpip/BackgroundLocationWatchdog.kt
new file mode 100644
index 000000000..c13fb318c
--- /dev/null
+++ b/android/app/src/main/kotlin/com/exptech/dpip/BackgroundLocationWatchdog.kt
@@ -0,0 +1,182 @@
+package com.exptech.dpip
+
+import android.content.Context
+import androidx.work.BackoffPolicy
+import androidx.work.ExistingPeriodicWorkPolicy
+import androidx.work.PeriodicWorkRequest
+import androidx.work.WorkInfo
+import androidx.work.WorkManager
+import androidx.work.Worker
+import androidx.work.WorkerParameters
+import java.util.concurrent.TimeUnit
+
+/**
+ * Durable self-healing layer behind the geofence and alarm paths.
+ *
+ * WorkManager is deliberately not a third location timer. A healthy run only
+ * verifies the unique work and restores a missing/expired alarm deadline. It
+ * asks the existing job path for a fix only after every native activity signal
+ * has been quiet longer than the alarm's maximum interval plus Doze grace.
+ */
+object BackgroundLocationWatchdog {
+ private const val UNIQUE_WORK = "background-location-watchdog"
+ private const val TAG = "background-location-watchdog"
+ private const val INTERVAL_MIN = 30L
+ private const val DOZE_GRACE_MIN = 15L
+ private const val TIMEOUT_MS =
+ (LocationAlarmScheduler.MAX_INTERVAL_MIN + DOZE_GRACE_MIN) * 60_000L
+
+ private const val KEY_LAST_RUN_AT = "watchdog_last_run_at"
+ private const val KEY_RUN_N = "watchdog_run_n"
+ private const val KEY_LAST_REPAIR_AT = "watchdog_last_repair_at"
+ private const val KEY_REPAIR_N = "watchdog_repair_n"
+ private const val KEY_BASELINE_AT = "watchdog_baseline_at"
+
+ /** Creates or updates the single watchdog without resetting its enqueue time. */
+ fun ensure(context: Context) {
+ if (!BgLocationStore.enabled(context)) return
+ val prefs = BgLocationStore.prefs(context)
+ if (!prefs.contains(KEY_BASELINE_AT)) {
+ // First enable has no wake/report evidence yet. Give the initial job
+ // the same 45-minute window before diagnostics call it overdue.
+ prefs.edit().putLong(KEY_BASELINE_AT, System.currentTimeMillis()).apply()
+ }
+ val request = PeriodicWorkRequest.Builder(
+ BackgroundLocationWatchdogWorker::class.java,
+ INTERVAL_MIN,
+ TimeUnit.MINUTES,
+ )
+ // `start` already queues the initial report. Waiting one period keeps
+ // first install/resume from producing a duplicate location request.
+ .setInitialDelay(INTERVAL_MIN, TimeUnit.MINUTES)
+ .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 10L, TimeUnit.MINUTES)
+ .addTag(TAG)
+ .build()
+ WorkManager.getInstance(context.applicationContext).enqueueUniquePeriodicWork(
+ UNIQUE_WORK,
+ // The specification is static, so KEEP avoids both duplicate work
+ // and an unnecessary WorkManager generation on every Flutter resume.
+ // REPLACE would postpone the watchdog on every native start.
+ ExistingPeriodicWorkPolicy.KEEP,
+ request,
+ )
+ }
+
+ fun cancel(context: Context) {
+ WorkManager.getInstance(context.applicationContext).cancelUniqueWork(UNIQUE_WORK)
+ BgLocationStore.prefs(context).edit().remove(KEY_BASELINE_AT).apply()
+ }
+
+ internal fun lastActivityAt(context: Context): Long {
+ val prefs = BgLocationStore.prefs(context)
+ return maxOf(
+ prefs.getLong("wake_alarm_at", 0L),
+ prefs.getLong("last_geofence_transition_at", 0L),
+ prefs.getLong(BgLocationStore.KEY_LAST_ATTEMPT_AT, 0L),
+ prefs.getLong(KEY_BASELINE_AT, 0L),
+ )
+ }
+
+ internal fun isOverdue(now: Long, lastActivityAt: Long): Boolean =
+ lastActivityAt <= 0L || now - lastActivityAt > TIMEOUT_MS
+
+ internal fun recordRun(context: Context, now: Long) {
+ val prefs = BgLocationStore.prefs(context)
+ prefs.edit()
+ .putLong(KEY_LAST_RUN_AT, now)
+ .putInt(KEY_RUN_N, prefs.getInt(KEY_RUN_N, 0) + 1)
+ .apply()
+ }
+
+ internal fun recordRepair(context: Context, now: Long) {
+ val prefs = BgLocationStore.prefs(context)
+ prefs.edit()
+ .putLong(KEY_LAST_REPAIR_AT, now)
+ .putInt(KEY_REPAIR_N, prefs.getInt(KEY_REPAIR_N, 0) + 1)
+ .apply()
+ }
+
+ /**
+ * Live WorkManager state plus persisted execution evidence for diagnostics.
+ * Call off the main thread because WorkManager's query is a future.
+ */
+ fun diagnostics(context: Context): Map {
+ val infos = try {
+ WorkManager.getInstance(context.applicationContext)
+ .getWorkInfosForUniqueWork(UNIQUE_WORK)
+ .get(2, TimeUnit.SECONDS)
+ } catch (_: Exception) {
+ null
+ }
+ val info = infos?.firstOrNull { !it.state.isFinished } ?: infos?.firstOrNull()
+ val prefs = BgLocationStore.prefs(context)
+ val lastActivityAt = lastActivityAt(context)
+ val state = info?.state
+ return mapOf(
+ "watchdogState" to when {
+ infos == null -> "query unavailable"
+ state == null -> "missing"
+ else -> state.name.lowercase()
+ },
+ "watchdogScheduled" to (state == WorkInfo.State.ENQUEUED ||
+ state == WorkInfo.State.BLOCKED || state == WorkInfo.State.RUNNING),
+ "watchdogNextAt" to info?.nextScheduleTimeMillis
+ ?.takeIf { it > 0L && it < Long.MAX_VALUE },
+ "watchdogLastRunAt" to prefs.getLong(KEY_LAST_RUN_AT, 0L).takeIf { it > 0L },
+ "watchdogRunCount" to prefs.getInt(KEY_RUN_N, 0),
+ "watchdogLastRepairAt" to prefs
+ .getLong(KEY_LAST_REPAIR_AT, 0L)
+ .takeIf { it > 0L },
+ "watchdogRepairCount" to prefs.getInt(KEY_REPAIR_N, 0),
+ "watchdogLastActivityAt" to lastActivityAt.takeIf { it > 0L },
+ "watchdogOverdue" to (BgLocationStore.enabled(context) &&
+ isOverdue(System.currentTimeMillis(), lastActivityAt)),
+ )
+ }
+}
+
+/** Periodic entry point; all expensive work remains in BackgroundLocationJobService. */
+class BackgroundLocationWatchdogWorker(
+ appContext: Context,
+ params: WorkerParameters,
+) : Worker(appContext, params) {
+ override fun doWork(): Result {
+ val app = applicationContext
+ val now = System.currentTimeMillis()
+ BackgroundLocationWatchdog.recordRun(app, now)
+ if (!BgLocationStore.enabled(app)) return Result.success()
+
+ // This is cheap and idempotent: a live future deadline is preserved;
+ // an expired/lost one is recreated without acquiring a location.
+ LocationAlarmScheduler.ensure(app)
+
+ val lastActivityAt = BackgroundLocationWatchdog.lastActivityAt(app)
+ if (!BackgroundLocationWatchdog.isOverdue(now, lastActivityAt)) {
+ return Result.success()
+ }
+
+ if (!GeofenceManager.hasPermission(app)) {
+ BgLocationStore.setArmed(app, false)
+ BgLocationStore.note(app, "watchdog: overdue, background location unavailable")
+ return Result.success()
+ }
+
+ BackgroundLocationWatchdog.recordRepair(app, now)
+ val quietFor = if (lastActivityAt <= 0L) {
+ "never active"
+ } else {
+ "quiet ${(now - lastActivityAt) / 60_000L} min"
+ }
+ BgLocationStore.note(app, "watchdog: repairing overdue path ($quietFor)")
+ return if (
+ BackgroundLocationJobService.enqueue(
+ app,
+ BackgroundLocationJobService.REASON_WATCHDOG,
+ )
+ ) {
+ Result.success()
+ } else {
+ Result.retry()
+ }
+ }
+}
diff --git a/android/app/src/main/kotlin/com/exptech/dpip/BgLocationStore.kt b/android/app/src/main/kotlin/com/exptech/dpip/BgLocationStore.kt
index 4cf9492a9..d9fb02c6d 100644
--- a/android/app/src/main/kotlin/com/exptech/dpip/BgLocationStore.kt
+++ b/android/app/src/main/kotlin/com/exptech/dpip/BgLocationStore.kt
@@ -7,8 +7,8 @@ import java.net.URL
/**
* Shared persistence + reporting for background device-location reporting, used
- * by both the primary geofence spine ([GeofenceManager]/[GeofenceReceiver]) and
- * the Google-Play-services-less alarm fallback ([LocationAlarmScheduler]).
+ * by both the geofence fast path ([GeofenceManager]/[GeofenceReceiver]) and the
+ * independent alarm fallback ([LocationAlarmScheduler]).
*
* State lives in prefs so any receiver can run with no Flutter isolate alive.
*/
@@ -21,16 +21,25 @@ object BgLocationStore {
const val KEY_LAST_LAT = "last_lat"
const val KEY_LAST_LNG = "last_lng"
const val KEY_HAS_LAST = "has_last"
- const val KEY_INTERVAL_MIN = "interval_min" // alarm fallback only
+ const val KEY_INTERVAL_MIN = "interval_min"
+ const val KEY_PERMISSION_READY = "permission_ready"
// Diagnostics. None of this drives behaviour — it exists so the developer
// page can answer "is background reporting actually working?" from a user's
// phone. The Geofencing API has no way to ask whether a fence is live, so
// whether one was ever armed has to be remembered here.
const val KEY_ARMED = "geofence_armed"
- const val KEY_LAST_REPORT_AT = "last_report_at"
- const val KEY_LAST_REPORT_OK = "last_report_ok"
- const val KEY_LAST_REPORT_CODE = "last_report_code"
+ const val KEY_LAST_ATTEMPT_AT = "last_attempt_at"
+ const val KEY_LAST_ATTEMPT_OK = "last_attempt_ok"
+ const val KEY_LAST_ATTEMPT_CODE = "last_attempt_code"
+ const val KEY_LAST_SUCCESS_AT = "last_success_at"
+ const val KEY_LAST_SUCCESS_CODE = "last_success_code"
+ const val KEY_LAST_THROTTLED_AT = "last_throttled_at"
+
+ // Read-only migration source for builds that predate split diagnostics.
+ const val KEY_LEGACY_LAST_REPORT_AT = "last_report_at"
+ const val KEY_LEGACY_LAST_REPORT_OK = "last_report_ok"
+ const val KEY_LEGACY_LAST_REPORT_CODE = "last_report_code"
/** When a report was last *sent*, which is what the throttle measures. */
const val KEY_LAST_SENT_AT = "last_sent_at"
@@ -43,6 +52,14 @@ object BgLocationStore {
fun enabled(context: Context): Boolean = prefs(context).getBoolean(KEY_ENABLED, false)
+ fun configMatches(context: Context, token: String, version: String, platform: Int): Boolean {
+ val prefs = prefs(context)
+ return prefs.getBoolean(KEY_ENABLED, false) &&
+ prefs.getString(KEY_TOKEN, null) == token &&
+ prefs.getString(KEY_VERSION, null) == version &&
+ prefs.getInt(KEY_PLATFORM, Int.MIN_VALUE) == platform
+ }
+
fun saveConfig(context: Context, token: String, version: String, platform: Int) {
prefs(context).edit()
.putBoolean(KEY_ENABLED, true)
@@ -56,10 +73,18 @@ object BgLocationStore {
prefs(context).edit()
.putBoolean(KEY_ENABLED, false)
.putBoolean(KEY_ARMED, false)
+ .putBoolean(KEY_PERMISSION_READY, false)
.apply()
}
- /** Records whether a geofence is currently monitoring — diagnostics only. */
+ fun permissionReady(context: Context): Boolean =
+ prefs(context).getBoolean(KEY_PERMISSION_READY, false)
+
+ fun setPermissionReady(context: Context, ready: Boolean) {
+ prefs(context).edit().putBoolean(KEY_PERMISSION_READY, ready).apply()
+ }
+
+ /** Records the last accepted geofence registration — diagnostics only. */
fun setArmed(context: Context, armed: Boolean) {
prefs(context).edit().putBoolean(KEY_ARMED, armed).apply()
}
@@ -87,7 +112,9 @@ object BgLocationStore {
* main thread). Best-effort: a failure is swallowed and retried on the next
* trigger. coreExclusiveApi is tnn1-only (no failover).
*/
+ @Synchronized
fun report(context: Context, lat: Double, lng: Double) {
+ if (!enabled(context)) return
val prefs = prefs(context)
// At most one report a minute, across every trigger.
@@ -99,29 +126,28 @@ object BgLocationStore {
// looks like it stopped reporting: on the device this was found on,
// `last_report_code` was 429 with the geofence armed and a fix in hand.
//
- // Measured from KEY_LAST_SENT_AT, not KEY_LAST_REPORT_AT: the latter is
- // stamped on every outcome including this one, so gating on it would
- // let a burst of triggers push the window ahead of itself and starve
- // reporting entirely.
+ // A throttled trigger is not a report attempt. Keep it in its own fields
+ // so it cannot overwrite the last HTTP result shown by diagnostics.
val now = System.currentTimeMillis()
val sent = prefs.getLong(KEY_LAST_SENT_AT, 0L)
if (sent > 0L && now - sent < MIN_REPORT_INTERVAL_MS) {
prefs.edit()
.putInt(KEY_THROTTLED_N, prefs.getInt(KEY_THROTTLED_N, 0) + 1)
+ .putLong(KEY_LAST_THROTTLED_AT, now)
.apply()
- stamp(prefs, THROTTLED)
return
}
- // Stamped even on the way out. These two returns sat *above* the stamp,
- // so a run that never had a token was indistinguishable from one that
- // never happened — and "never happened" is what the developer page
- // showed for both, which is the ambiguity that made this bug survive
- // three attempts. A negative code is a reason, not an HTTP status.
+ // A negative code is a reason no HTTP request could be made.
val token = prefs.getString(KEY_TOKEN, null)
- ?: return stamp(prefs, NO_TOKEN)
+ ?: return stampAttempt(prefs, now, NO_TOKEN)
val version = prefs.getString(KEY_VERSION, null)
- ?: return stamp(prefs, NO_VERSION)
+ ?: return stampAttempt(prefs, now, NO_VERSION)
val platform = prefs.getInt(KEY_PLATFORM, 0)
+
+ // Reserve the one-minute slot before opening the connection. Multiple
+ // JobWorkItems and a foreground report can otherwise pass the throttle
+ // together and issue duplicate requests.
+ prefs.edit().putLong(KEY_LAST_SENT_AT, now).apply()
var code = -1
try {
val url = URL(
@@ -135,7 +161,6 @@ object BgLocationStore {
code = responseCode // fire the request
disconnect()
}
- prefs.edit().putLong(KEY_LAST_SENT_AT, now).apply()
} catch (e: Exception) {
// Best-effort; the next trigger retries. The outcome is still
// recorded below — "tried at T and failed" is the diagnostic that
@@ -148,12 +173,15 @@ object BgLocationStore {
// a timeout, a TLS failure and a Doze network block equally well.
note(context, "report failed: ${e.javaClass.simpleName}")
}
- stamp(prefs, code)
+ stampAttempt(prefs, now, code)
+ if (code in 200..299) {
+ prefs.edit()
+ .putLong(KEY_LAST_SUCCESS_AT, now)
+ .putInt(KEY_LAST_SUCCESS_CODE, code)
+ .apply()
+ }
}
- /** Dropped by the throttle — a report went out less than a minute ago. */
- const val THROTTLED = -4
-
/** The floor between two reports, whichever trigger asks. */
const val MIN_REPORT_INTERVAL_MS = 60_000L
@@ -163,11 +191,11 @@ object BgLocationStore {
/** No app version stored, which the endpoint's path needs. */
const val NO_VERSION = -3
- private fun stamp(prefs: SharedPreferences, code: Int) {
+ private fun stampAttempt(prefs: SharedPreferences, at: Long, code: Int) {
prefs.edit()
- .putLong(KEY_LAST_REPORT_AT, System.currentTimeMillis())
- .putBoolean(KEY_LAST_REPORT_OK, code in 200..299)
- .putInt(KEY_LAST_REPORT_CODE, code)
+ .putLong(KEY_LAST_ATTEMPT_AT, at)
+ .putBoolean(KEY_LAST_ATTEMPT_OK, code in 200..299)
+ .putInt(KEY_LAST_ATTEMPT_CODE, code)
.apply()
}
@@ -175,12 +203,10 @@ object BgLocationStore {
* A bounded ring of what the background path did, drained into the app's
* own log at the next launch.
*
- * Every background wake runs in a `BroadcastReceiver` with no Flutter
- * isolate, so nothing it does can reach `Log` — and `android.util.Log` is
- * logcat, which nobody can read from their own phone. The Android
- * background path was therefore invisible *by construction*, which is why
- * three attempts at this bug had nothing to go on.
+ * Every background wake begins in a receiver and continues in a native job,
+ * with no Flutter isolate, so nothing it does can reach `Log` as it happens.
*/
+ @Synchronized
fun note(context: Context, message: String) {
val prefs = prefs(context)
val existing = prefs.getString(KEY_BREADCRUMBS, "").orEmpty()
@@ -191,6 +217,7 @@ object BgLocationStore {
}
/** Reads the ring and clears it, so a line is reported once. */
+ @Synchronized
fun drainBreadcrumbs(context: Context): List {
val prefs = prefs(context)
val all = prefs.getString(KEY_BREADCRUMBS, "").orEmpty()
@@ -208,6 +235,7 @@ object BgLocationStore {
* trace, so "the OS never called us" and "we ignored the call" looked
* identical.
*/
+ @Synchronized
fun noteWake(context: Context, kind: String) {
val prefs = prefs(context)
prefs.edit()
diff --git a/android/app/src/main/kotlin/com/exptech/dpip/FusedFix.kt b/android/app/src/main/kotlin/com/exptech/dpip/FusedFix.kt
index f184bcb6f..90d6bfac1 100644
--- a/android/app/src/main/kotlin/com/exptech/dpip/FusedFix.kt
+++ b/android/app/src/main/kotlin/com/exptech/dpip/FusedFix.kt
@@ -17,7 +17,7 @@ import java.util.concurrent.TimeUnit
* township boundary, so it never spins the battery-hungry GPS chip. Accepts a
* recent cached fix (`maxUpdateAge`) to avoid a fresh acquisition when possible,
* and falls back to the last known location. Blocks briefly — call off the main
- * thread (the receivers' `goAsync` window).
+ * thread (normally [BackgroundLocationJobService]).
*
* Returns null when it cannot get one, which is a real outcome on a device with
* no Play services, no location permission, or location switched off — and
diff --git a/android/app/src/main/kotlin/com/exptech/dpip/GeofenceManager.kt b/android/app/src/main/kotlin/com/exptech/dpip/GeofenceManager.kt
index f749181b7..4031d7327 100644
--- a/android/app/src/main/kotlin/com/exptech/dpip/GeofenceManager.kt
+++ b/android/app/src/main/kotlin/com/exptech/dpip/GeofenceManager.kt
@@ -87,10 +87,12 @@ object GeofenceManager {
/**
* (Re-)registers the geofence centred on ([lat], [lng]). Adding a geofence
* with the same id replaces the previous one, so this re-centres in place.
- * The centre is persisted only once registration actually succeeds, so a
- * failed (re-)arm can't leave the store believing a dead fence is live.
+ * The centre is persisted only once Play services accepts registration, so
+ * a refused re-arm cannot replace the last usable centre. Acceptance is not
+ * treated as proof that transitions are healthy; only [GeofenceReceiver]
+ * may defer the independent alarm after a real EXIT delivery.
*
- * [onArmed] reports whether a fence is actually monitoring afterwards.
+ * [onArmed] reports whether Play services accepted the registration.
* Registration is asynchronous, so a caller that needs to know — the one
* deciding whether the alarm fallback can be stood down — cannot infer it
* from this function returning. It is invoked on the main looper (Play
@@ -108,6 +110,10 @@ object GeofenceManager {
lng: Double,
onArmed: ((Boolean) -> Unit)? = null,
) {
+ if (!BgLocationStore.enabled(context)) {
+ onArmed?.invoke(false)
+ return
+ }
if (!hasPermission(context)) {
Log.w(TAG, "background/fine location not granted — geofence not armed")
BgLocationStore.setArmed(context, false)
@@ -133,14 +139,22 @@ object GeofenceManager {
// initial triggers yields enter events only — so adding an ENTER bit
// here would silently cost the self-heal this line exists for.
//
- // Best-effort, not a guarantee, which is what the alarm watchdog
- // behind the fence is for. See LocationAlarmScheduler.resetWatchdog.
+ // Best-effort, not a guarantee; the independent alarm remains
+ // scheduled even after registration succeeds.
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_EXIT)
.addGeofence(geofence)
.build()
LocationServices.getGeofencingClient(context)
.addGeofences(request, pendingIntent(context))
.addOnSuccessListener {
+ // stop() can race an in-flight binder request. If it won while
+ // Play services was answering, remove the late registration
+ // instead of resurrecting background work after disable.
+ if (!BgLocationStore.enabled(context)) {
+ remove(context)
+ onArmed?.invoke(false)
+ return@addOnSuccessListener
+ }
BgLocationStore.saveLast(context, lat, lng)
BgLocationStore.setArmed(context, true)
onArmed?.invoke(true)
diff --git a/android/app/src/main/kotlin/com/exptech/dpip/GeofenceReceiver.kt b/android/app/src/main/kotlin/com/exptech/dpip/GeofenceReceiver.kt
index 77710267b..52aaaec79 100644
--- a/android/app/src/main/kotlin/com/exptech/dpip/GeofenceReceiver.kt
+++ b/android/app/src/main/kotlin/com/exptech/dpip/GeofenceReceiver.kt
@@ -6,117 +6,41 @@ import android.content.Intent
import com.google.android.gms.location.Geofence
import com.google.android.gms.location.GeofencingEvent
-/**
- * Fires when the device **exits** its current geofence: re-centres the geofence
- * around the fresh triggering point, then reports the township.
- *
- * Because the geofence is monitored by (and this broadcast dispatched through)
- * the Google Play services process, it keeps working after our own app process
- * is killed by an OEM battery manager — the key robustness win over the in-app
- * alarm. The fix + re-register + POST run off the main thread in a `goAsync`
- * window; everything reads from [BgLocationStore] so no Flutter isolate is
- * needed.
- *
- * The geofence is re-centred on `event.triggeringLocation` — the location that
- * caused the exit, which is fresh and by definition *outside* the old fence, so
- * (unlike a possibly-stale last-known fix) the new fence is correctly centred on
- * where the device actually is. Re-centring runs BEFORE the POST so a mid-work
- * process kill can't leave the spine un-armed (the report is retried on the next
- * move). If the platform supplies no triggering location and no fresh fix, or on
- * a geofence error, it re-arms around the last centre — combined with
- * `INITIAL_TRIGGER_EXIT` an already-outside device re-fires immediately, so the
- * spine self-heals instead of dying. Best-effort, not a guarantee, which is
- * what the alarm watchdog behind the fence is for.
- */
+/** Records geofence delivery and hands location, registration, and HTTP to a job. */
class GeofenceReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
- val appContext = context.applicationContext
- // Before the guard: "the OS never woke us" and "we ignored the wake"
- // used to look identical, and they need different fixes.
- BgLocationStore.noteWake(appContext, "geofence")
- if (!BgLocationStore.enabled(appContext)) return
+ val app = context.applicationContext
+ BgLocationStore.noteWake(app, "geofence")
+ if (!BgLocationStore.enabled(app)) return
+
val event = GeofencingEvent.fromIntent(intent) ?: return
if (event.hasError()) {
- // The error code *is* the diagnosis, and it was read and thrown
- // away. GEOFENCE_NOT_AVAILABLE (1000, usually Google Location
- // Accuracy off), TOO_MANY_GEOFENCES (1001) and
- // TOO_MANY_PENDING_INTENTS (1002) are three unrelated bugs with
- // three unrelated fixes and one identical silent outcome.
- BgLocationStore.prefs(appContext).edit()
+ BgLocationStore.setArmed(app, false)
+ BgLocationStore.prefs(app).edit()
.putInt("last_geofence_error", event.errorCode)
.putLong("last_geofence_error_at", System.currentTimeMillis())
.apply()
- BgLocationStore.note(appContext, "geofence error ${event.errorCode}")
- // Before the re-arm, and unconditionally. An error broadcast is the
- // strongest evidence there is that the spine is gone, so it must
- // pull the alarm in to the adaptive interval — never leave it out at
- // the watchdog hour on the strength of an `armed` flag that this
- // very broadcast disproves. The re-arm below is asynchronous and
- // this branch does not hold the broadcast open, so its callback may
- // never land at all.
- LocationAlarmScheduler.ensure(appContext)
- reArm(appContext) // service dropped the fence (e.g. location toggled)
+ BgLocationStore.note(app, "geofence error ${event.errorCode}")
+ LocationAlarmScheduler.ensure(app)
+ BackgroundLocationJobService.enqueue(
+ app,
+ BackgroundLocationJobService.REASON_GEOFENCE_ERROR,
+ )
return
}
if (event.geofenceTransition != Geofence.GEOFENCE_TRANSITION_EXIT) return
- // The fence just did its job, which is the strongest evidence there is
- // that it works, so the watchdog's hour starts again from here — before
- // any of the work below, all of which can fail. A fence firing on
- // schedule keeps pushing the alarm out ahead of itself and it never
- // actually runs; an hour of fence silence is what lets it through.
- //
- // Deliberately below the error branch. An error broadcast is proof that
- // Play services can reach us, but it is also proof that the fence is
- // *gone* — petting the watchdog there would push the alarm out by an
- // hour at the exact moment the spine broke. That path re-arms instead,
- // and falls back to the adaptive alarm when the re-arm is refused.
- LocationAlarmScheduler.resetWatchdog(appContext)
-
- val pending = goAsync()
- Thread {
- try {
- val location = event.triggeringLocation ?: FusedFix.get(appContext)
- if (location != null && BgLocationStore.enabled(appContext)) {
- // Re-centre first (spine safety), then report (best-effort).
- // A refused re-centre leaves this device with no fence and
- // no alarm — the exit that got us here already consumed the
- // old one — so the fallback catches it.
- GeofenceManager.register(
- appContext, location.latitude, location.longitude,
- ) { armed -> if (!armed) LocationAlarmScheduler.ensure(appContext) }
- BgLocationStore.report(appContext, location.latitude, location.longitude)
- } else if (location == null) {
- // No fix at all — re-arm around the last centre so a future
- // EXIT can still fire (the current fence is already exited).
- reArm(appContext)
- }
- } catch (e: Exception) {
- // Best-effort.
- } finally {
- pending.finish()
- }
- }.start()
- }
- /// Re-arms around the last known centre after the platform dropped the
- /// fence, and falls back to the alarm if it cannot.
- ///
- /// This is the path a `GEOFENCE_NOT_AVAILABLE` takes, and the reason the
- /// fallback matters most here: that error usually means the user just
- /// turned Location off, so the re-arm attempted in the same breath is
- /// almost certain to fail. Without the fallback the device is left with no
- /// fence and — on a Play-services device, where the geofence is the only
- /// spine — no alarm either, and nothing that will ever notice. Turning
- /// Location back on does not re-arm anything: Play services does not
- /// restore removed geofences, and no broadcast brings us back.
- private fun reArm(context: Context) {
- if (!BgLocationStore.enabled(context)) return
- if (!BgLocationStore.hasLast(context)) {
- LocationAlarmScheduler.ensure(context)
- return
- }
- GeofenceManager.register(
- context, BgLocationStore.lastLat(context), BgLocationStore.lastLng(context),
- ) { armed -> if (!armed) LocationAlarmScheduler.ensure(context) }
+ // Registration success is only an accepted request. A delivered EXIT is
+ // the sole proof that the fast path works, and the only event allowed to
+ // defer the independent alarm to its thirty-minute ceiling.
+ BgLocationStore.prefs(app).edit()
+ .putLong("last_geofence_transition_at", System.currentTimeMillis())
+ .apply()
+ LocationAlarmScheduler.onGeofenceTransition(app)
+ BackgroundLocationJobService.enqueue(
+ app,
+ BackgroundLocationJobService.REASON_GEOFENCE_EXIT,
+ event.triggeringLocation,
+ )
}
}
diff --git a/android/app/src/main/kotlin/com/exptech/dpip/GmsAvailability.kt b/android/app/src/main/kotlin/com/exptech/dpip/GmsAvailability.kt
index f6edda322..45d23c915 100644
--- a/android/app/src/main/kotlin/com/exptech/dpip/GmsAvailability.kt
+++ b/android/app/src/main/kotlin/com/exptech/dpip/GmsAvailability.kt
@@ -8,7 +8,8 @@ import com.google.android.gms.common.GoogleApiAvailability
* Whether Google Play services (which host the Fused Location Provider and the
* Geofencing API) are usable on this device. Selects the background spine: the
* low-power geofence when present, the framework-`LocationManager` alarm
- * fallback ([LocationAlarmScheduler]) on de-Googled devices.
+ * geofence fast path. [LocationAlarmScheduler] remains active independently on
+ * every device.
*/
object GmsAvailability {
fun available(context: Context): Boolean =
diff --git a/android/app/src/main/kotlin/com/exptech/dpip/LocationAlarmReceiver.kt b/android/app/src/main/kotlin/com/exptech/dpip/LocationAlarmReceiver.kt
index e547efe10..15be03e4c 100644
--- a/android/app/src/main/kotlin/com/exptech/dpip/LocationAlarmReceiver.kt
+++ b/android/app/src/main/kotlin/com/exptech/dpip/LocationAlarmReceiver.kt
@@ -3,135 +3,20 @@ package com.exptech.dpip
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
-import android.location.Location
-import java.util.concurrent.CountDownLatch
-import java.util.concurrent.TimeUnit
-/**
- * The GMS-less fallback alarm handler: gets one framework-`LocationManager` fix,
- * reports the township, and keeps the interval adapting to how far the device
- * moved (see [LocationAlarmScheduler]). Devices with Google Play services use
- * the geofence spine instead.
- *
- * **Chain continuity:** the next alarm is armed *up front* — before the fix and
- * HTTP work — so a mid-work process kill can't permanently break the
- * self-rescheduling chain; it's then refined to the adapted interval. Runs off
- * the main thread in a `goAsync` window; state comes from [BgLocationStore].
- *
- * **The chain never has an exit.** It used to: this receiver cancelled itself
- * the moment Play services confirmed a fence was live. That is now a lengthening
- * to [LocationAlarmScheduler.WATCHDOG_MIN] instead, because a fence
- * that registers is not a fence that fires, and cancelling on `armed` made a
- * fence that had quietly stopped firing indistinguishable from a device that
- * was not moving. Only turning reporting off stops the chain.
- */
+/** Records an alarm wake, preserves the chain, and hands all work to JobScheduler. */
class LocationAlarmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
- val appContext = context.applicationContext
- BgLocationStore.noteWake(appContext, "alarm")
- if (!BgLocationStore.enabled(appContext)) return
+ val app = context.applicationContext
+ BgLocationStore.noteWake(app, "alarm")
+ if (!BgLocationStore.enabled(app)) return
- val prefs = BgLocationStore.prefs(appContext)
- // The adaptive fallback interval, which is maintained below whatever the
- // fence is doing — so this stays the right answer for the moment the
- // fence stops being the spine. It is NOT necessarily the delay to use.
- val stored = prefs.getLong(
- BgLocationStore.KEY_INTERVAL_MIN,
- LocationAlarmScheduler.DEFAULT_INTERVAL_MIN,
+ // Preserve continuity before handing off: if this process dies while the
+ // job is waiting for a fix or HTTP, another alarm still exists.
+ LocationAlarmScheduler.schedule(app, LocationAlarmScheduler.storedInterval(app))
+ BackgroundLocationJobService.enqueue(
+ app,
+ BackgroundLocationJobService.REASON_ALARM,
)
- // Arm the next alarm BEFORE any blocking work, so the chain survives a
- // kill during the fix/network wait. The delay comes from
- // `nextDelayMinutes`, not from `stored`: behind a live fence this is a
- // watchdog on an hour, and reading `stored` here is what would collapse
- // it back to the adaptive interval on the first firing.
- LocationAlarmScheduler.schedule(appContext, LocationAlarmScheduler.nextDelayMinutes(appContext))
-
- val pending = goAsync()
- Thread {
- try {
- val location = LocationFetcher.getFix(appContext)
- val next = if (location != null) {
- val n = LocationAlarmScheduler.nextIntervalMinutes(
- distanceFromLast(appContext, location), stored,
- )
- BgLocationStore.saveLast(appContext, location.latitude, location.longitude)
- prefs.edit().putLong(BgLocationStore.KEY_INTERVAL_MIN, n).apply()
- BgLocationStore.report(appContext, location.latitude, location.longitude)
- n
- } else {
- // No fix — back off toward the max like the stationary case.
- val n = (stored + 5).coerceAtMost(LocationAlarmScheduler.MAX_INTERVAL_MIN)
- prefs.edit().putLong(BgLocationStore.KEY_INTERVAL_MIN, n).apply()
- n
- }
- // Refine the provisional alarm to the adapted interval.
- //
- // The order used to matter a great deal: the hand-back below
- // cancelled the alarm from a callback, so anything that
- // scheduled afterwards won the race and left it running for
- // good. Now that arming only lengthens the alarm, losing that
- // race costs a shorter interval instead of a silent device —
- // which is the direction a race on a safety path should fail in.
- if (next != stored && BgLocationStore.enabled(appContext)) {
- LocationAlarmScheduler.schedule(appContext, next)
- }
- // Hand back to the geofence, which is the spine worth having:
- // Play services keeps monitoring it after an OEM battery manager
- // kills this process, and a parked phone costs it zero wakeups.
- //
- // Unconditional on a GMS device, and that is the point. This used
- // to be gated on `!BgLocationStore.armed()`, i.e. "only climb back
- // if we believe no fence is live" — which made the chain
- // inescapable in the one state that matters. `armed` is a stored
- // belief, and several paths arm this alarm without clearing it
- // (a resume whose fix times out indoors is the everyday one, see
- // BackgroundLocationChannel.armGeofence). Once the alarm was
- // running while the flag said `true`, the guard skipped the
- // re-register, so nothing ever reached the cancel — while the
- // top of onReceive rescheduled the next firing unconditionally.
- // Both spines then ran forever: a wakeup, a GPS fix and a POST
- // every 10 minutes that the geofence was already covering.
- //
- // Re-registering is cheap and idempotent (a fixed request id
- // replaces in place), and standing down on Play services'
- // confirmation rather than on the flag also repairs a stale
- // `armed` instead of trusting it.
- if (location != null &&
- GmsAvailability.available(appContext) &&
- BgLocationStore.enabled(appContext)
- ) {
- val settled = CountDownLatch(1)
- GeofenceManager.register(
- appContext, location.latitude, location.longitude,
- ) { armed ->
- if (armed) LocationAlarmScheduler.resetWatchdog(appContext)
- settled.countDown()
- }
- // The callback lands on the main looper, which is free — this
- // is a worker thread inside goAsync, so awaiting it is safe.
- // Capped well inside the broadcast window: if Play services
- // does not answer in time the alarm simply survives to the
- // next firing, which is the correct fallback anyway.
- settled.await(10, TimeUnit.SECONDS)
- }
- } catch (e: Exception) {
- // The provisional alarm is already armed — leave it as the backstop.
- } finally {
- pending.finish()
- }
- }.start()
- }
-
- private fun distanceFromLast(context: Context, location: Location): Double? {
- if (!BgLocationStore.hasLast(context)) return null
- val results = FloatArray(1)
- Location.distanceBetween(
- BgLocationStore.lastLat(context),
- BgLocationStore.lastLng(context),
- location.latitude,
- location.longitude,
- results,
- )
- return results[0].toDouble()
}
}
diff --git a/android/app/src/main/kotlin/com/exptech/dpip/LocationAlarmScheduler.kt b/android/app/src/main/kotlin/com/exptech/dpip/LocationAlarmScheduler.kt
index 72bb147b9..a1c0abe52 100644
--- a/android/app/src/main/kotlin/com/exptech/dpip/LocationAlarmScheduler.kt
+++ b/android/app/src/main/kotlin/com/exptech/dpip/LocationAlarmScheduler.kt
@@ -7,34 +7,30 @@ import android.content.Intent
import android.os.SystemClock
/**
- * Timing policy + scheduling for the **GMS-less fallback** background spine.
+ * Independent, bounded fallback behind Android's geofence fast path.
*
- * On devices with Google Play services the primary spine is the low-power
- * geofence ([GeofenceManager]); this adaptive-interval alarm is the fallback for
- * de-Googled devices, where geofencing/FLP are unavailable. A single
- * self-rescheduling alarm adapts its interval to distance moved — short when
- * moving, backing off to an hour when still — using Doze-friendly inexact
- * `setAndAllowWhileIdle`. Config/last-fix live in [BgLocationStore].
- *
- * Deliberate tradeoff: `setAndAllowWhileIdle` is throttled in Doze to roughly
- * one fire per ~9 min, so [MIN_INTERVAL_MIN] is best-effort — accepted here to
- * avoid a foreground service or the exact-alarm permission.
+ * The alarm is always present while reporting is enabled. It adapts between
+ * ten and thirty minutes and never trusts the stored `geofence_armed` belief:
+ * successful registration only proves that Play services accepted a request,
+ * not that a future transition will be delivered. Only a real EXIT transition
+ * may push the deadline back to the thirty-minute ceiling.
*/
object LocationAlarmScheduler {
private const val REQUEST_CODE = 888888
- const val MIN_INTERVAL_MIN = 5L
+ const val MIN_INTERVAL_MIN = 10L
const val DEFAULT_INTERVAL_MIN = 10L
- const val MAX_INTERVAL_MIN = 60L
+ const val MAX_INTERVAL_MIN = 30L
+
private const val HIGH_MOVEMENT_M = 1000.0
private const val LOW_MOVEMENT_M = 100.0
+ private const val MINUTE_MS = 60_000L
- /**
- * The next interval (minutes) given the [distanceMeters] moved since the last
- * fix: 5 min moving fast (≥1 km), 10 min moving a little (≥100 m), otherwise
- * back off +5 min up to an hour. A null distance (no previous fix) uses the
- * default.
- */
+ private const val KEY_SCHEDULED = "alarm_scheduled"
+ private const val KEY_NEXT_ELAPSED = "alarm_next_elapsed"
+ private const val KEY_NEXT_WALL = "alarm_next_wall"
+
+ /** Chooses the next bounded fallback interval from movement since the last fix. */
fun nextIntervalMinutes(distanceMeters: Double?, currentMinutes: Long): Long =
when {
distanceMeters == null -> DEFAULT_INTERVAL_MIN
@@ -43,122 +39,87 @@ object LocationAlarmScheduler {
else -> (currentMinutes + 5).coerceAtMost(MAX_INTERVAL_MIN)
}
- /** Schedules the next wake-up [delayMinutes] from now (inexact, Doze-friendly). */
+ /** Schedules a fresh deadline and records the actual target for diagnostics. */
fun schedule(context: Context, delayMinutes: Long) {
- val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
- val triggerAt = SystemClock.elapsedRealtime() + delayMinutes * 60_000L
- am.setAndAllowWhileIdle(
- AlarmManager.ELAPSED_REALTIME_WAKEUP,
- triggerAt,
- pendingIntent(context),
+ val bounded = delayMinutes.coerceIn(MIN_INTERVAL_MIN, MAX_INTERVAL_MIN)
+ scheduleAt(
+ context,
+ SystemClock.elapsedRealtime() + bounded * MINUTE_MS,
+ System.currentTimeMillis() + bounded * MINUTE_MS,
)
}
/**
- * Schedules the fallback at its stored interval — the "the geofence did not
- * take, don't leave this device with nothing" path.
- *
- * Every place that arms a geofence needs this, because every one of them can
- * fail: the channel on app start, [GeofenceReceiver] re-centring after an
- * exit or recovering from a GEOFENCE_NOT_AVAILABLE, and
- * [LocationBootReceiver] after a reboot. A failure with no fallback is
- * silent and permanent — the geofence is the only spine on a Play-services
- * device, so nothing is left to notice or retry.
- *
- * Always the adaptive interval, never [WATCHDOG_MIN], and deliberately not
- * [nextDelayMinutes]. Every call site of this function is a site that has
- * just established there is *no* fence, so the stored `armed` belief can
- * only be wrong here — and wrong in the expensive direction, handing a
- * fenceless device an hour of silence instead of five minutes.
+ * Restores the existing deadline without moving it. If it already expired,
+ * starts a new bounded interval. This makes repeated native `start` calls
+ * idempotent instead of postponing the fallback every time Flutter resumes.
*/
fun ensure(context: Context) {
if (!BgLocationStore.enabled(context)) return
- val interval = BgLocationStore.prefs(context)
- .getLong(BgLocationStore.KEY_INTERVAL_MIN, DEFAULT_INTERVAL_MIN)
- schedule(context, interval)
+ val prefs = BgLocationStore.prefs(context)
+ val elapsed = prefs.getLong(KEY_NEXT_ELAPSED, 0L)
+ val wall = prefs.getLong(KEY_NEXT_WALL, 0L)
+ if (elapsed > SystemClock.elapsedRealtime() && wall > System.currentTimeMillis()) {
+ scheduleAt(context, elapsed, wall)
+ return
+ }
+ schedule(context, storedInterval(context))
}
- /**
- * How long the geofence may stay silent before the alarm goes looking.
- *
- * A geofence that arms is not a geofence that fires. The fence went live on
- * a Pixel 9, the alarm was cancelled because it had, and the device then
- * reported nothing for 133 minutes — no wake, no error, nothing to notice.
- * `dumpsys alarm` held no pending alarm, `geofence_armed` was true, and the
- * only breadcrumb was "arm: geofence live". Cancelling on `armed` made "the
- * fence is working" and "the fence is dead" the same observation.
- *
- * So the alarm is a watchdog now, and the fence is what pets it: every time
- * the fence proves it is alive the hour starts again, and the alarm only
- * ever actually fires after a full hour of fence silence. Behind a working
- * fence that costs nothing — a moving device re-arms far more often than
- * hourly, so the alarm is perpetually pushed out and never runs.
- */
- const val WATCHDOG_MIN = 60L
-
- /**
- * The delay the next alarm should use, given what the spine currently is.
- *
- * Two regimes, one switch. With a geofence armed the alarm is a watchdog and
- * the fence is the spine, so an hour is right. With no fence — a de-Googled
- * device, or one where registration was refused — the alarm *is* the spine,
- * and [nextIntervalMinutes]' adaptive 5–60 is right.
- *
- * Read from [BgLocationStore.armed] rather than from a second stored
- * interval on purpose. [BgLocationStore.KEY_INTERVAL_MIN] stays what it has
- * always been — the adaptive fallback value — and goes on being maintained
- * underneath a live fence, so a device whose fence dies drops straight back
- * onto a current interval instead of a stale one.
- *
- * `armed` is a belief, and nothing clears it when a fence dies quietly, so
- * this can say "watchdog" about a device that has no fence. That is the one
- * place the belief is allowed to be wrong: it costs an hour, which is the
- * bound the watchdog was chosen to give in the first place. [ensure] is the
- * function for every site that *knows* there is no fence.
- */
- fun nextDelayMinutes(context: Context): Long =
- if (BgLocationStore.armed(context)) {
- WATCHDOG_MIN
- } else {
- BgLocationStore.prefs(context)
- .getLong(BgLocationStore.KEY_INTERVAL_MIN, DEFAULT_INTERVAL_MIN)
- }
+ /** Recreates elapsed-realtime state after a reboot, when the old clock is invalid. */
+ fun restartAfterBoot(context: Context) {
+ if (!BgLocationStore.enabled(context)) return
+ schedule(context, DEFAULT_INTERVAL_MIN)
+ }
- /**
- * Restarts the hour, for when the geofence has just proved it is alive.
- *
- * Both proofs count: a fence that *arms* is talking to Play services, and a
- * fence that *fires* is doing its job. Either one resets the countdown.
- *
- * Deliberately not [cancel]: the fence is the fast path, not the only path.
- */
- fun resetWatchdog(context: Context) {
+ /** A real transition is the only event allowed to defer the fallback. */
+ fun onGeofenceTransition(context: Context) {
if (!BgLocationStore.enabled(context)) return
- schedule(context, WATCHDOG_MIN)
+ schedule(context, MAX_INTERVAL_MIN)
}
- /** Cancels any pending wake-up. Only for turning reporting off entirely. */
+ fun storedInterval(context: Context): Long =
+ BgLocationStore.prefs(context)
+ .getLong(BgLocationStore.KEY_INTERVAL_MIN, DEFAULT_INTERVAL_MIN)
+ .coerceIn(MIN_INTERVAL_MIN, MAX_INTERVAL_MIN)
+
+ /** Cancels the OS alarm. Only used when reporting is disabled. */
fun cancel(context: Context) {
val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
am.cancel(pendingIntent(context))
+ BgLocationStore.prefs(context).edit()
+ .putBoolean(KEY_SCHEDULED, false)
+ .remove(KEY_NEXT_ELAPSED)
+ .remove(KEY_NEXT_WALL)
+ .apply()
}
/**
- * Whether an alarm is currently pending — diagnostics only.
+ * Whether this process successfully asked AlarmManager for a wake-up.
*
- * `FLAG_NO_CREATE` returns null when no matching PendingIntent exists, which
- * is the only way to ask AlarmManager "is something scheduled?"; there is no
- * query API. It must carry the same flags and request code as
- * [pendingIntent] or it will not match.
+ * AlarmManager has no query API. `PendingIntent.FLAG_NO_CREATE` only says a
+ * matching PendingIntent token exists and stays non-null after cancellation,
+ * so it must not be used as evidence that an alarm is scheduled.
*/
- fun isScheduled(context: Context): Boolean {
- val intent = Intent(context, LocationAlarmReceiver::class.java)
- return PendingIntent.getBroadcast(
- context,
- REQUEST_CODE,
- intent,
- PendingIntent.FLAG_NO_CREATE or PendingIntent.FLAG_IMMUTABLE,
- ) != null
+ fun isScheduled(context: Context): Boolean =
+ BgLocationStore.enabled(context) &&
+ BgLocationStore.prefs(context).getBoolean(KEY_SCHEDULED, false)
+
+ fun nextWallTime(context: Context): Long? =
+ BgLocationStore.prefs(context).getLong(KEY_NEXT_WALL, 0L).takeIf { it > 0L }
+
+ private fun scheduleAt(context: Context, elapsed: Long, wall: Long) {
+ val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
+ am.setAndAllowWhileIdle(
+ AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ elapsed,
+ pendingIntent(context),
+ )
+ BgLocationStore.prefs(context).edit()
+ .putBoolean(KEY_SCHEDULED, true)
+ .putLong(KEY_NEXT_ELAPSED, elapsed)
+ .putLong(KEY_NEXT_WALL, wall)
+ .apply()
}
private fun pendingIntent(context: Context): PendingIntent {
diff --git a/android/app/src/main/kotlin/com/exptech/dpip/LocationBootReceiver.kt b/android/app/src/main/kotlin/com/exptech/dpip/LocationBootReceiver.kt
index 97815d4b6..67c72f50d 100644
--- a/android/app/src/main/kotlin/com/exptech/dpip/LocationBootReceiver.kt
+++ b/android/app/src/main/kotlin/com/exptech/dpip/LocationBootReceiver.kt
@@ -4,57 +4,27 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
-/**
- * Re-arms the background spine after a reboot.
- *
- * Geofences are cleared by the system on reboot (and on a Play-services update
- * or app-data clear), and the fallback alarm uses elapsed-realtime triggers that
- * also clear — so without this a device that reboots would silently stop
- * reporting. Re-registers the geofence around the last centre (GMS) or the
- * fallback alarm (de-Googled), only when reporting was enabled.
- */
+/** Restores scheduling after reboot/update and delegates repair to JobScheduler. */
class LocationBootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
- val appContext = context.applicationContext
- BgLocationStore.noteWake(appContext, "boot")
- // MY_PACKAGE_REPLACED as well as BOOT_COMPLETED: an app update cancels
- // every alarm the package had scheduled and Android does not restore
- // them, so a device that updates and is not opened loses its spine
- // silently — which is exactly the state a user who "installed the fix"
- // would be in.
+ val app = context.applicationContext
+ BgLocationStore.noteWake(app, "boot")
if (intent.action != Intent.ACTION_BOOT_COMPLETED &&
intent.action != Intent.ACTION_MY_PACKAGE_REPLACED
) {
return
}
- if (!BgLocationStore.enabled(appContext)) return
+ if (!BgLocationStore.enabled(app)) return
- if (!GmsAvailability.available(appContext) || !BgLocationStore.hasLast(appContext)) {
- LocationAlarmScheduler.ensure(appContext)
- return
- }
- // Registration is a binder call into Play services, so hold the
- // broadcast open until it answers — the other two receivers already do,
- // and without it this one can be killed mid-flight. It also carries the
- // fallback: BOOT_COMPLETED regularly lands before GMS location is ready,
- // and a not-yet-initialised network location provider is exactly what
- // returns GEOFENCE_NOT_AVAILABLE. A boot that failed to arm used to
- // leave the device silent until the user next opened the app.
- val pending = goAsync()
- GeofenceManager.register(
- appContext, BgLocationStore.lastLat(appContext), BgLocationStore.lastLng(appContext),
- ) { armed ->
- // Both branches schedule, and they must. A reboot clears every
- // elapsed-realtime alarm the package had, and an app update cancels
- // them too — so at this point the device has none, and the success
- // branch returning without scheduling is the one path that leaves a
- // fence with nothing at all behind it.
- if (armed) {
- LocationAlarmScheduler.resetWatchdog(appContext)
- } else {
- LocationAlarmScheduler.ensure(appContext)
- }
- pending.finish()
+ if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
+ LocationAlarmScheduler.restartAfterBoot(app)
+ } else {
+ LocationAlarmScheduler.ensure(app)
}
+ BackgroundLocationWatchdog.ensure(app)
+ BackgroundLocationJobService.enqueue(
+ app,
+ BackgroundLocationJobService.REASON_BOOT,
+ )
}
}
diff --git a/android/app/src/main/kotlin/com/exptech/dpip/LocationFetcher.kt b/android/app/src/main/kotlin/com/exptech/dpip/LocationFetcher.kt
index 8f47ff8d6..7f1b8a58f 100644
--- a/android/app/src/main/kotlin/com/exptech/dpip/LocationFetcher.kt
+++ b/android/app/src/main/kotlin/com/exptech/dpip/LocationFetcher.kt
@@ -21,11 +21,10 @@ import java.util.concurrent.TimeUnit
* Prefers a recent last-known fix (no sensor spin-up) and only asks the system
* for a fresh one when that's stale. For a township-level report (~500 m is
* plenty) it prefers the low-power **network** provider over GPS, and it
- * requires background-location permission on Android 10+ — a headless receiver
- * with only "while in use" can't fix, so this returns null and the receiver
- * backs off rather than spinning sensors for nothing. Runs on the caller's
- * background thread (the alarm receiver's `goAsync` window), blocking briefly on
- * the fresh-fix callback via a latch.
+ * requires background-location permission on Android 10+ — a headless job with
+ * only "while in use" cannot fix, so this returns null and the alarm backs off
+ * rather than spinning sensors for nothing. Runs on the caller's background
+ * thread, blocking briefly on the fresh-fix callback via a latch.
*/
object LocationFetcher {
private const val FRESH_MS = 5 * 60 * 1000L
diff --git a/android/app/src/main/kotlin/com/exptech/dpip/MainActivity.kt b/android/app/src/main/kotlin/com/exptech/dpip/MainActivity.kt
index fa72cd34c..aa29937f7 100644
--- a/android/app/src/main/kotlin/com/exptech/dpip/MainActivity.kt
+++ b/android/app/src/main/kotlin/com/exptech/dpip/MainActivity.kt
@@ -44,8 +44,11 @@ class MainActivity : FlutterActivity() {
MethodChannel(messenger, BatteryOptimizationChannel.NAME)
.setMethodCallHandler(BatteryOptimizationChannel(applicationContext))
+ MethodChannel(messenger, PermissionSettingsChannel.NAME)
+ .setMethodCallHandler(PermissionSettingsChannel(applicationContext))
+
MethodChannel(messenger, UnusedAppRestrictionsChannel.NAME)
- .setMethodCallHandler(UnusedAppRestrictionsChannel(applicationContext))
+ .setMethodCallHandler(UnusedAppRestrictionsChannel(this))
MethodChannel(messenger, BackgroundExecutionChannel.NAME)
.setMethodCallHandler(BackgroundExecutionChannel(applicationContext))
diff --git a/android/app/src/main/kotlin/com/exptech/dpip/PermissionSettingsChannel.kt b/android/app/src/main/kotlin/com/exptech/dpip/PermissionSettingsChannel.kt
new file mode 100644
index 000000000..6078bed7c
--- /dev/null
+++ b/android/app/src/main/kotlin/com/exptech/dpip/PermissionSettingsChannel.kt
@@ -0,0 +1,67 @@
+package com.exptech.dpip
+
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.provider.Settings
+import android.util.Log
+import io.flutter.plugin.common.MethodCall
+import io.flutter.plugin.common.MethodChannel
+
+/** Android-owned labels and app-specific Settings destinations.
+ *
+ * A generic app-details intent is a poor fallback for every permission: Android
+ * exposes a dedicated notification page, and Android 11+ exposes the exact,
+ * localized label the user must choose for background location. Keeping those
+ * details native also means the Flutter guide matches the device language even
+ * when DPIP itself is using a different locale.
+ */
+class PermissionSettingsChannel(private val context: Context) :
+ MethodChannel.MethodCallHandler {
+
+ companion object {
+ const val NAME = "com.exptech.dpip/permission_settings"
+ private const val TAG = "PermissionSettings"
+ }
+
+ override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
+ when (call.method) {
+ "backgroundLocationOptionLabel" -> result.success(backgroundLocationOptionLabel())
+ "openNotificationSettings" -> result.success(openNotificationSettings())
+ else -> result.notImplemented()
+ }
+ }
+
+ private fun backgroundLocationOptionLabel(): String? {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) return null
+ return context.packageManager.backgroundPermissionOptionLabel.toString()
+ }
+
+ /** Opens DPIP's own notification switch, with app details as a safe fallback. */
+ private fun openNotificationSettings(): String {
+ try {
+ context.startActivity(
+ Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
+ .putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
+ )
+ return "notifications"
+ } catch (e: Exception) {
+ Log.i(TAG, "app notification settings unavailable", e)
+ }
+
+ return try {
+ context.startActivity(
+ Intent(
+ Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
+ Uri.parse("package:${context.packageName}"),
+ ).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
+ )
+ "appDetails"
+ } catch (e: Exception) {
+ Log.w(TAG, "no notification settings screen could be opened", e)
+ "none"
+ }
+ }
+}
diff --git a/android/app/src/main/kotlin/com/exptech/dpip/UnusedAppRestrictionsChannel.kt b/android/app/src/main/kotlin/com/exptech/dpip/UnusedAppRestrictionsChannel.kt
index ea6967502..da2f453ee 100644
--- a/android/app/src/main/kotlin/com/exptech/dpip/UnusedAppRestrictionsChannel.kt
+++ b/android/app/src/main/kotlin/com/exptech/dpip/UnusedAppRestrictionsChannel.kt
@@ -1,7 +1,9 @@
package com.exptech.dpip
+import android.app.Activity
import android.content.Context
import android.content.Intent
+import android.os.Build
import androidx.core.content.ContextCompat
import androidx.core.content.IntentCompat
import androidx.core.content.PackageManagerCompat
@@ -37,24 +39,28 @@ import io.flutter.plugin.common.MethodChannel
* state on a days-not-months timescale and are not reachable through this API;
* they need the user to exempt the app in the vendor's own battery UI.
*/
-class UnusedAppRestrictionsChannel(private val context: Context) :
+class UnusedAppRestrictionsChannel(private val activity: Activity) :
MethodChannel.MethodCallHandler {
companion object {
const val NAME = "com.exptech.dpip/unused_app_restrictions"
+ private const val REQUEST_CODE = 4102
}
+ private val context: Context get() = activity.applicationContext
+
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
"status" -> status(result)
+ "guide" -> result.success(guide())
"openSettings" -> {
try {
val intent = IntentCompat.createManageUnusedAppRestrictionsIntent(
context, context.packageName,
- ).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- context.startActivity(intent)
- result.success(null)
+ )
+ openForResult(intent)
+ result.success(true)
} catch (e: Exception) {
result.error("unused_app_restrictions_failed", e.message, null)
}
@@ -64,6 +70,24 @@ class UnusedAppRestrictionsChannel(private val context: Context) :
}
}
+ /** The Settings label/path Android documents for each platform generation. */
+ private fun guide(): String {
+ return when {
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> "pause"
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> "freeSpace"
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> "revoke"
+ else -> "playProtect"
+ }
+ }
+
+ // IntentCompat explicitly requires the result-based launch even though the
+ // result code itself carries no useful state; the current exemption is
+ // re-read when Flutter resumes.
+ @Suppress("DEPRECATION")
+ private fun openForResult(intent: Intent) {
+ activity.startActivityForResult(intent, REQUEST_CODE)
+ }
+
/**
* Resolves to `"exempt"`, `"restricted"` or `"unavailable"`.
*
diff --git a/api.md b/api.md
index 484f737a1..c87742b02 100644
--- a/api.md
+++ b/api.md
@@ -52,14 +52,16 @@
## 沒多活備援 (single host, no failover)
-### Basemap / Terrain(全域 static LB,無區域)
+### Basemap / OSM / Terrain(全域 static LB,無區域)
-Basemap 與 terrain 都由 MapLibre 直接抓(app 的 tile bridge 會以 URL 為鍵快取),
-不經 `ApiClient` 的區域 failover。
+Basemap、OSM 詳細街道建築與 terrain 都由 MapLibre 直接抓(app 的 tile bridge
+會以 URL 為鍵快取),不經 `ApiClient` 的區域 failover。OSM 是可選疊圖,只覆蓋
+臺灣資料範圍;一般 basemap 始終保留,因此資料範圍外不會變成空白。
| 用途 | 路徑 | 主機 |
|---|---|---|
| basemap | `/api/v1/map/tiles/{z}/{x}/{y}.pbf` | `static.lb.exptech.dev` |
+| OSM 詳細圖資 | `/api/v1/map/gsi/{z}/{x}/{y}.pbf` | `static.lb.exptech.dev` |
| terrain | `/api/v1/map/terrain/{z}/{x}/{y}.png` | `static.lb.exptech.dev` |
> **Terrain 是 Mapbox terrain-RGB,MapLibre 原生讀得懂。** 每個像素編碼
diff --git a/lib/app/app.dart b/lib/app/app.dart
index 11b5c6096..4f71a36c1 100644
--- a/lib/app/app.dart
+++ b/lib/app/app.dart
@@ -21,7 +21,6 @@ import 'package:dpip/core/settings/region_store.dart';
import 'package:dpip/core/settings/color_vision_controller.dart';
import 'package:dpip/core/settings/display_settings.dart';
import 'package:dpip/core/settings/theme_controller.dart';
-import 'package:dpip/l10n/gen/app_localizations.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:provider/single_child_widget.dart';
@@ -95,8 +94,7 @@ class DpipApp extends StatelessWidget {
themeMode: themeController.mode,
locale: localeController.locale,
localeListResolutionCallback: resolveAppLocale,
- localizationsDelegates:
- AppLocalizations.localizationsDelegates,
+ localizationsDelegates: appLocalizationsDelegates,
// Home locale first, so an unmatched device language falls back to
// Traditional Chinese (Taiwan), not the English template.
supportedLocales: appSupportedLocales,
diff --git a/lib/core/diagnostics/debug_dump.dart b/lib/core/diagnostics/debug_dump.dart
index a6b9fedd2..4de99f6f6 100644
--- a/lib/core/diagnostics/debug_dump.dart
+++ b/lib/core/diagnostics/debug_dump.dart
@@ -12,6 +12,37 @@ const int dumpLimit = 39995;
const String _diagnosticsHeading = '=== 除錯資訊 ===';
const String _logHeading = '=== 日誌紀錄 ===';
+final RegExp _coordinateValue = RegExp(
+ r'((?:"|\b)(?:centreLat|centerLat|centreLng|centerLng|latitude|longitude|lat|lon|lng)"?\s*[:=]\s*)(-?\d+(?:\.\d+)?)',
+ caseSensitive: false,
+);
+
+final RegExp _coordinatePair = RegExp(
+ r'(^|[^\d.])(-?\d{1,2}\.\d{3,})\s*,\s*(-?\d{1,3}\.\d{3,})([^\d.]|$)',
+ multiLine: true,
+);
+
+/// Removes precise locations from the final text immediately before upload.
+///
+/// Structured diagnostics are nulled by label before this point. This final
+/// boundary also covers coordinates embedded in free-form log lines, including
+/// the native background-location path which is not represented by
+/// [DiagnosticsField]. Device identifiers and push tokens deliberately remain:
+/// they are support lookup keys, while the coordinates are the personal value
+/// the user must explicitly consent to send. The literal `null` is intentional:
+/// silently deleting a value makes a reader mistake privacy filtering for
+/// missing diagnostics.
+String redactSensitiveDump(String content) {
+ final redacted = content.replaceAllMapped(
+ _coordinateValue,
+ (match) => '${match[1]}null',
+ );
+ return redacted.replaceAllMapped(
+ _coordinatePair,
+ (match) => '${match[1]}null,null${match[4]}',
+ );
+}
+
/// Builds the dump: diagnostics whole, then as much log as still fits.
///
/// [logLines] is newest first — the order the store and Talker's history both
diff --git a/lib/core/diagnostics/diagnostics_report.dart b/lib/core/diagnostics/diagnostics_report.dart
index 04aee7529..f18e71918 100644
--- a/lib/core/diagnostics/diagnostics_report.dart
+++ b/lib/core/diagnostics/diagnostics_report.dart
@@ -50,26 +50,22 @@ typedef DiagnosticsReport = ({
List tables,
});
-/// Labels that never leave the device.
+/// Values that require explicit consent before a diagnostics upload.
///
-/// Dropped rather than starred out: these are the values in the dump that
-/// identify a person or authorise a push to them, and a dump is pasted into
-/// places its author does not control. One list, because a second copy is a
-/// list that drifts — and the copy that drifts is the one that leaks.
-const Set diagnosticsRedactedLabels = {
- 'Identifier',
- 'FCM token',
- 'APNs token',
-};
+/// One list owns the policy so the confirmation copy and the upload path cannot
+/// drift. Without consent these labels stay visible but their values become the
+/// literal `null`, making the omission unambiguous to whoever reads the dump.
+const Set diagnosticsSensitiveLabels = {'Centred on'};
/// The sections as the text that gets pasted.
///
-/// Labels in [redacted] are dropped entirely rather than starred out: a device
-/// identifier and a push token are the two values in here that identify a
-/// person, and a dump is pasted into places its author does not control.
+/// Labels in [redacted] are dropped entirely. Labels in [nulled] remain in the
+/// report with the literal value `null`, so support can distinguish a privacy
+/// choice from a platform that failed to answer the diagnostic.
String diagnosticsText(
List sections, {
Set redacted = const {},
+ Set nulled = const {},
}) {
final buffer = StringBuffer('DPIP diagnostics');
for (final section in sections) {
@@ -80,7 +76,8 @@ String diagnosticsText(
if (fields.isEmpty) continue;
buffer.writeln('\n[${section.title}]');
for (final field in fields) {
- buffer.writeln('${field.label}: ${field.value ?? '—'}');
+ final value = nulled.contains(field.label) ? 'null' : field.value ?? '—';
+ buffer.writeln('${field.label}: $value');
}
}
return buffer.toString().trim();
@@ -105,16 +102,87 @@ String _yesNo(Object? value) => switch (value) {
/// are the difference between working and dead, and the failed case is worth
/// showing rather than hiding — a device that fires and gets a 500 needs a
/// different fix from one that never fires.
-String _lastReport(Map d) {
- final at = d['lastReportAt'];
+String _lastAttempt(Map d) {
+ final at = d['lastAttemptAt'] ?? d['lastReportAt'];
if (at is! int) return 'never';
final when = DateTime.fromMillisecondsSinceEpoch(at);
final age = DateTime.now().difference(when);
- final ok = d['lastReportOk'] == true;
- final code = d['lastReportCode'];
+ final ok = (d['lastAttemptOk'] ?? d['lastReportOk']) == true;
+ final code = d['lastAttemptCode'] ?? d['lastReportCode'];
return '${_age(age)} ago · ${_outcome(ok, code)}';
}
+/// Last confirmed 2xx result, kept apart from the most recent failed attempt.
+String _lastSuccess(Map d) {
+ final fallback = d['lastReportOk'] == true ? d['lastReportAt'] : null;
+ final at = d['lastSuccessAt'] ?? fallback;
+ if (at is! int) return 'never';
+ final code = d['lastSuccessCode'] ?? d['lastReportCode'];
+ return '${_age(DateTime.now().difference(DateTime.fromMillisecondsSinceEpoch(at)))} '
+ 'ago${code is int ? ' · $code' : ''}';
+}
+
+/// Throttle skips are expected control flow, not failed report attempts.
+String _throttled(Map d) {
+ final count = d['throttledCount'];
+ if (count is! int || count == 0) return 'none';
+ final at = d['lastThrottledAt'];
+ if (at is! int) return '$count';
+ final age = DateTime.now().difference(
+ DateTime.fromMillisecondsSinceEpoch(at),
+ );
+ return '$count · last ${_age(age)} ago';
+}
+
+String _nextAlarm(Map d) {
+ final at = d['nextAlarmAt'];
+ if (at is! int) return '—';
+ final remaining = DateTime.fromMillisecondsSinceEpoch(at)
+ .difference(DateTime.now());
+ if (remaining.isNegative) return 'due (OS may deliver it late)';
+ return 'in ${_age(remaining)}';
+}
+
+String _relativeTime(Object? value, {required String absent}) {
+ if (value is! int) return absent;
+ final delta = DateTime.fromMillisecondsSinceEpoch(value)
+ .difference(DateTime.now());
+ return delta.isNegative ? '${_age(-delta)} ago' : 'in ${_age(delta)}';
+}
+
+String _watchdog(Map d) {
+ final state = d['watchdogState'] as String? ?? 'unknown';
+ final health = switch (state) {
+ 'query unavailable' => 'health unknown',
+ _ when d['watchdogScheduled'] != true => 'NOT SCHEDULED',
+ _ when d['watchdogOverdue'] == true => 'OVERDUE',
+ _ => 'healthy',
+ };
+ final next = _relativeTime(d['watchdogNextAt'], absent: 'next unknown');
+ return '$state · $health · $next';
+}
+
+String _watchdogRuns(Map d) {
+ final count = d['watchdogRunCount'];
+ final last = _relativeTime(d['watchdogLastRunAt'], absent: 'never');
+ return '${count is int ? count : 0} · last $last';
+}
+
+String _watchdogRepairs(Map d) {
+ final count = d['watchdogRepairCount'];
+ final last = _relativeTime(d['watchdogLastRepairAt'], absent: 'never');
+ return '${count is int ? count : 0} · last $last';
+}
+
+String _lastGeofenceTransition(Map d) {
+ final at = d['lastGeofenceTransitionAt'];
+ if (at is! int) return 'never';
+ final age = DateTime.now().difference(
+ DateTime.fromMillisecondsSinceEpoch(at),
+ );
+ return '${_age(age)} ago';
+}
+
/// A negative code is a reason the request was never made, not an HTTP status.
/// It has to read as one: `failed (-2)` sends whoever pastes it looking for a
/// network fault that never happened.
@@ -336,7 +404,25 @@ class DiagnosticsCollector {
label: 'Geofence error',
value: bgLocation['lastGeofenceError'] as String?,
),
- (label: 'Last report', value: _lastReport(bgLocation)),
+ if (bgLocation.containsKey('lastGeofenceTransitionAt'))
+ (
+ label: 'Last geofence exit',
+ value: _lastGeofenceTransition(bgLocation),
+ ),
+ (label: 'Last attempt', value: _lastAttempt(bgLocation)),
+ (label: 'Last success', value: _lastSuccess(bgLocation)),
+ if (bgLocation.containsKey('throttledCount'))
+ (label: 'Throttle skips', value: _throttled(bgLocation)),
+ if (bgLocation.containsKey('nextAlarmAt'))
+ (label: 'Next alarm', value: _nextAlarm(bgLocation)),
+ if (bgLocation.containsKey('watchdogState')) ...[
+ (label: 'Watchdog', value: _watchdog(bgLocation)),
+ (label: 'Watchdog runs', value: _watchdogRuns(bgLocation)),
+ (
+ label: 'Watchdog repair attempts',
+ value: _watchdogRepairs(bgLocation),
+ ),
+ ],
(label: 'Centred on', value: _centre(bgLocation)),
(label: 'Detail', value: bgLocation['detail'] as String?),
(
diff --git a/lib/core/geo/location_monitor.dart b/lib/core/geo/location_monitor.dart
index 92c0ba82d..85b31bd4e 100644
--- a/lib/core/geo/location_monitor.dart
+++ b/lib/core/geo/location_monitor.dart
@@ -116,7 +116,7 @@ class LocationMonitor extends ChangeNotifier with WidgetsBindingObserver {
s == LocationStatus.ready || s == LocationStatus.whileInUseOnly;
/// Sends the user to system settings to fix the permission / services toggle.
- Future openSettings() => _location.openSettings();
+ Future openSettings() => _location.openSettings();
@override
void dispose() {
diff --git a/lib/core/geo/location_service.dart b/lib/core/geo/location_service.dart
index 543e15c87..aded18ce4 100644
--- a/lib/core/geo/location_service.dart
+++ b/lib/core/geo/location_service.dart
@@ -66,9 +66,9 @@ class LocationService {
/// Opens the system app-settings so the user can grant a permission that can't
/// be requested in-app (permanently denied, or Android 11+ background
/// location). Best-effort.
- Future openSettings() async {
+ Future openSettings() async {
Log.info('permission: opening app settings');
- await openAppSettingsPage();
+ return openAppSettingsPage();
}
/// Requests **foreground** location permission (call from a screen, after
diff --git a/lib/core/network/api_paths.dart b/lib/core/network/api_paths.dart
index 4c16846a7..0d0ac2be4 100644
--- a/lib/core/network/api_paths.dart
+++ b/lib/core/network/api_paths.dart
@@ -18,6 +18,11 @@ abstract final class ApiPaths {
/// v1 basemap vector tiles (`/api/v1/map/tiles/…`).
static const String mapTilesV1 = '/api/v1/map/tiles/';
+ /// Detailed Taiwan street/building vector tiles
+ /// (`/api/v1/map/gsi/{z}/{x}/{y}.pbf`). The route name is legacy; the
+ /// payload is OpenMapTiles data sourced from OpenStreetMap, not Japan GSI.
+ static const String mapOsmV1 = '/api/v1/map/gsi/';
+
/// v1 terrain vector tiles (`/api/v1/map/terrain/…`) — the static CDN's
/// elevation mesh, same XYZ shape as [mapTilesV1].
static const String mapTerrainV1 = '/api/v1/map/terrain/';
diff --git a/lib/core/network/etag_interceptor.dart b/lib/core/network/etag_interceptor.dart
index 9e7ad69f9..d8f35e5b4 100644
--- a/lib/core/network/etag_interceptor.dart
+++ b/lib/core/network/etag_interceptor.dart
@@ -70,10 +70,11 @@ class EtagInterceptor extends Interceptor {
static bool _isBytes(RequestOptions o) =>
o.responseType == ResponseType.bytes;
- /// Bare-host basemap vector tiles (no server ETag).
+ /// Bare-host static map vector tiles (no server ETag).
static bool isBasemapPbf(Uri uri) =>
uri.host == 'static.lb.exptech.dev' &&
- uri.path.contains(ApiPaths.mapTilesV1) &&
+ (uri.path.contains(ApiPaths.mapTilesV1) ||
+ uri.path.contains(ApiPaths.mapOsmV1)) &&
uri.path.endsWith('.pbf');
/// URL fragments marking a **content-addressed** asset: the URL fully
@@ -91,6 +92,7 @@ class EtagInterceptor extends Interceptor {
/// app's usage accounting.
static const List immutableAssetMarkers = [
ApiPaths.mapTilesV1, // basemap vector tiles
+ ApiPaths.mapOsmV1, // detailed Taiwan street/building vector tiles
ApiPaths.mapTerrainV1, // terrain vector tiles
'${ApiPaths.tiles}/radar/',
'${ApiPaths.tiles}/satellite/',
diff --git a/lib/core/notifications/notification_service.dart b/lib/core/notifications/notification_service.dart
index 768b49106..3994d6e3a 100644
--- a/lib/core/notifications/notification_service.dart
+++ b/lib/core/notifications/notification_service.dart
@@ -205,12 +205,12 @@ class NotificationService {
/// Opens the OS notification settings for this app — the fallback when a
/// permission cannot be granted from inside the app any more.
- Future openSystemSettings() async {
+ Future openSystemSettings() async {
Log.info('permission: opening notification settings');
// Not awesome's `showNotificationConfigPage` — on iOS that returned
// without navigating anywhere and without an error, which is how the
// "Open Settings" button became the next thing that did nothing.
- await openAppSettingsPage();
+ return openNotificationSettingsPage();
}
Future _initChannels() async {
diff --git a/lib/core/permissions/permission_health.dart b/lib/core/permissions/permission_health.dart
index 9a35869ab..6768cdb85 100644
--- a/lib/core/permissions/permission_health.dart
+++ b/lib/core/permissions/permission_health.dart
@@ -41,10 +41,9 @@ import 'package:flutter/widgets.dart';
/// a *high-priority* FCM message already wakes a dozing device and is handed
/// a temporary wakelock and network, so the alert path itself survives Doze
/// without any exemption. What the exemption buys is everything that makes
-/// the alert *timely* — `setAndAllowWhileIdle` is throttled to roughly one
-/// fire per nine minutes under Doze, which puts the alarm spine's five-minute
-/// floor out of reach on exactly the devices where that alarm is the only
-/// spine (no Play services, or a geofence that would not arm); a
+/// the alert *timely* — `setAndAllowWhileIdle` may be deferred under Doze,
+/// which stretches the independent alarm fallback on every Android device;
+/// a
/// normal-priority message is deferred until Doze lifts; and geofence
/// transitions are delayed. On a disaster app the latency *is* the product;
/// - **critical alerts** (iOS). They are what makes a life-threatening warning
diff --git a/lib/core/permissions/system_settings.dart b/lib/core/permissions/system_settings.dart
index fc48e3d43..56be10205 100644
--- a/lib/core/permissions/system_settings.dart
+++ b/lib/core/permissions/system_settings.dart
@@ -12,9 +12,52 @@
/// everywhere or fails everywhere — never one row silently.
library;
+import 'dart:io';
+
import 'package:dpip/core/logging/log.dart';
+import 'package:flutter/services.dart';
import 'package:permission_handler/permission_handler.dart' as ph;
+/// Android destinations and labels that the cross-platform permission plugin
+/// cannot express. Public for a narrow MethodChannel test seam.
+class AndroidPermissionSettings {
+ AndroidPermissionSettings([MethodChannel? channel])
+ : _channel =
+ channel ??
+ const MethodChannel('com.exptech.dpip/permission_settings');
+
+ final MethodChannel _channel;
+
+ /// The device-localized Settings choice for background access (Android 11+).
+ Future backgroundLocationOptionLabel() async {
+ try {
+ return await _channel.invokeMethod(
+ 'backgroundLocationOptionLabel',
+ );
+ } on PlatformException catch (error, stackTrace) {
+ Log.handle(error, stackTrace, 'background location option label');
+ return null;
+ } on MissingPluginException {
+ return null;
+ }
+ }
+
+ /// Opens DPIP's own notification switch rather than generic app details.
+ Future openNotificationSettings() async {
+ try {
+ return await _channel.invokeMethod('openNotificationSettings') ??
+ 'none';
+ } on PlatformException catch (error, stackTrace) {
+ Log.handle(error, stackTrace, 'notification settings');
+ return 'none';
+ } on MissingPluginException {
+ return 'none';
+ }
+ }
+}
+
+final AndroidPermissionSettings _androidSettings = AndroidPermissionSettings();
+
/// Returns whether the settings page was actually opened, which is the part
/// worth logging: a `false` here is the difference between "the user chose not
/// to grant it" and "the button does nothing".
@@ -28,3 +71,19 @@ Future openAppSettingsPage() async {
return false;
}
}
+
+/// Opens the narrowest notification destination available on each platform.
+Future openNotificationSettingsPage() async {
+ if (!Platform.isAndroid) return openAppSettingsPage();
+ final destination = await _androidSettings.openNotificationSettings();
+ if (destination != 'none') {
+ Log.info('permission: notification settings -> $destination');
+ return true;
+ }
+ return openAppSettingsPage();
+}
+
+/// Returns Android's own localized background-location choice when available.
+Future backgroundLocationOptionLabel() => Platform.isAndroid
+ ? _androidSettings.backgroundLocationOptionLabel()
+ : Future.value();
diff --git a/lib/core/platform/background_execution.dart b/lib/core/platform/background_execution.dart
index 7c65c16e4..8a3596323 100644
--- a/lib/core/platform/background_execution.dart
+++ b/lib/core/platform/background_execution.dart
@@ -89,17 +89,22 @@ class BackgroundExecutionService {
}
}
- /// Opens the vendor's battery screen where one exists, else the app's own
- /// system settings page. Returns what it managed to open (`vendor`,
- /// `appDetails`, `none`) so the caller can say where the user landed instead
- /// of assuming — the vendor screens are several menus from where any generic
- /// instruction would put them.
- Future openSettings() async {
+ /// Opens the page for the platform's own background-execution switch.
+ ///
+ /// iOS already exposes that page through the older `openOemSettings` method;
+ /// keep using it so an Android-only routing refinement cannot strand iOS.
+ Future openSystemSettings() =>
+ _open(Platform.isIOS ? 'openOemSettings' : 'openSystemSettings');
+
+ /// Opens the vendor's battery screen where one exists, else app details.
+ Future openOemSettings() => _open('openOemSettings');
+
+ Future _open(String method) async {
if (!Platform.isAndroid && !Platform.isIOS) return 'none';
try {
- return await _channel.invokeMethod('openOemSettings') ?? 'none';
+ return await _channel.invokeMethod(method) ?? 'none';
} on PlatformException catch (error, stackTrace) {
- Log.handle(error, stackTrace, 'background execution openSettings');
+ Log.handle(error, stackTrace, 'background execution $method');
return 'none';
} on MissingPluginException {
return 'none';
diff --git a/lib/core/platform/background_location.dart b/lib/core/platform/background_location.dart
index 0febbabc5..94f3d148e 100644
--- a/lib/core/platform/background_location.dart
+++ b/lib/core/platform/background_location.dart
@@ -13,8 +13,9 @@ import 'package:flutter/services.dart';
/// visit monitoring (survives termination).
/// • Android — a low-power **EXIT geofence** via the Fused Location Provider,
/// monitored by Google Play services so it survives our process being killed
-/// by an OEM battery manager; a de-Googled device falls back to a
-/// distance-adaptive alarm.
+/// by an OEM battery manager; an independent 10–30 minute alarm repairs
+/// silent geofence loss and covers devices without Play services. A durable
+/// WorkManager watchdog repairs the alarm path only after it goes overdue.
/// Platform ([platform]: 1 iOS / 0 Android) and app [version] are fixed at
/// construction; only the push token varies per call.
///
@@ -59,9 +60,11 @@ class BackgroundLocationService {
/// Both platforms answer with the same keys, so one UI renders both:
/// `enabled` (the app asked for it), `authorization` (always / whenInUse /
/// denied / restricted / notDetermined), `armed` (something is monitoring
- /// **now**), `spine` (which mechanism), `hasToken`, `lastReportAt` (epoch ms),
- /// `lastReportOk`, `lastReportCode`, `centreLat` / `centreLng` (where the
- /// fence or region sits) and a free-text `detail` line of platform specifics.
+ /// **now**), `spine` (which mechanism), `hasToken`, report-attempt/success
+ /// timestamps and outcomes, `centreLat` / `centreLng` (where the fence or
+ /// region sits) and a free-text `detail` line of platform specifics. Android
+ /// additionally exposes throttle skips, the next alarm, and live WorkManager
+ /// watchdog state.
///
/// `armed` is the one that matters: every other value can look healthy on a
/// device that is silently reporting nothing.
diff --git a/lib/core/platform/battery_optimization.dart b/lib/core/platform/battery_optimization.dart
index 260993432..04bf6b5ef 100644
--- a/lib/core/platform/battery_optimization.dart
+++ b/lib/core/platform/battery_optimization.dart
@@ -32,14 +32,17 @@ class BatteryOptimization {
/// Opens the system exemption prompt. Re-check [isIgnoring] afterwards (e.g. on
/// app resume) — the user acts in a system dialog we can't await.
- Future request() async {
- if (!Platform.isAndroid) return;
+ Future request() async {
+ if (!Platform.isAndroid) return false;
try {
await _channel.invokeMethod('request');
+ return true;
} on PlatformException catch (error, stackTrace) {
Log.handle(error, stackTrace, 'battery request');
+ return false;
} on MissingPluginException {
// Unsupported platform / test harness — nothing to do.
+ return false;
}
}
}
diff --git a/lib/core/platform/unused_app_restrictions.dart b/lib/core/platform/unused_app_restrictions.dart
index 2eb33e722..4f881b54c 100644
--- a/lib/core/platform/unused_app_restrictions.dart
+++ b/lib/core/platform/unused_app_restrictions.dart
@@ -23,6 +23,9 @@ enum UnusedAppRestrictions {
unavailable,
}
+/// The Android-version-specific control the official intent opens near.
+enum UnusedAppSettingsGuide { pause, freeSpace, revoke, playProtect }
+
/// Reports and opens Android's unused-app-restrictions setting.
///
/// This is the failure mode that hits exactly the users background reporting
@@ -64,16 +67,35 @@ class UnusedAppRestrictionsService {
}
}
+ Future guide() async {
+ if (!Platform.isAndroid) return UnusedAppSettingsGuide.pause;
+ try {
+ return switch (await _channel.invokeMethod('guide')) {
+ 'freeSpace' => UnusedAppSettingsGuide.freeSpace,
+ 'revoke' => UnusedAppSettingsGuide.revoke,
+ 'playProtect' => UnusedAppSettingsGuide.playProtect,
+ _ => UnusedAppSettingsGuide.pause,
+ };
+ } on PlatformException catch (error, stackTrace) {
+ Log.handle(error, stackTrace, 'unused app restrictions guide');
+ return UnusedAppSettingsGuide.pause;
+ } on MissingPluginException {
+ return UnusedAppSettingsGuide.pause;
+ }
+ }
+
/// Opens the system page where the exemption lives. Re-check [status] on
/// resume — the user acts in a settings screen we can't await.
- Future openSettings() async {
- if (!Platform.isAndroid) return;
+ Future openSettings() async {
+ if (!Platform.isAndroid) return false;
try {
- await _channel.invokeMethod('openSettings');
+ return await _channel.invokeMethod('openSettings') ?? false;
} on PlatformException catch (error, stackTrace) {
Log.handle(error, stackTrace, 'unused app restrictions openSettings');
+ return false;
} on MissingPluginException {
// Unsupported platform / test harness — nothing to open.
+ return false;
}
}
}
diff --git a/lib/core/settings/locale_config.dart b/lib/core/settings/locale_config.dart
index b5a633806..32e77af23 100644
--- a/lib/core/settings/locale_config.dart
+++ b/lib/core/settings/locale_config.dart
@@ -2,7 +2,9 @@
library;
import 'package:dpip/l10n/gen/app_localizations.dart';
-import 'package:flutter/widgets.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_localizations/flutter_localizations.dart';
/// The app's home locale: Traditional Chinese for Taiwan (`zh_TW`).
///
@@ -28,6 +30,69 @@ List get appSupportedLocales => [
),
];
+/// The app's localization delegates, with a widgets-layer fallback for
+/// locales [flutter_localizations] does not ship (yue): Cantonese strings
+/// come from our own ARB, but Material/Cupertino built-in widget strings
+/// (date pickers, dialogs, …) fall back to Traditional Chinese — the closest
+/// written form the framework ships — instead of asserting.
+///
+/// [flutter_localizations] has no `yue`; a `MaterialApp` whose supported
+/// locales include it crashes at startup with "a Cupertino/Material delegate
+/// that supports the yue locale was not found". These fallback delegates
+/// pre-empt the framework's own `Global*` ones for exactly those locales.
+List> get appLocalizationsDelegates => [
+ ...AppLocalizations.localizationsDelegates,
+ const _WidgetsFallbackDelegate(
+ loadWith: _loadMaterial,
+ unsupported: [Locale('yue')],
+ replacement: kHomeLocale,
+ ),
+ const _WidgetsFallbackDelegate(
+ loadWith: _loadCupertino,
+ unsupported: [Locale('yue')],
+ replacement: kHomeLocale,
+ ),
+];
+
+Future _loadMaterial(Locale locale) =>
+ GlobalMaterialLocalizations.delegate.load(locale);
+
+Future _loadCupertino(Locale locale) =>
+ GlobalCupertinoLocalizations.delegate.load(locale);
+
+/// Forwards a widgets delegate for locales it cannot serve to a
+/// [replacement], and passes every other locale through to the underlying
+/// `Global*` delegate untouched.
+///
+/// A delegate that answers "not supported" gets skipped entirely by
+/// [Localizations], so the fallback has to pre-empt the framework's own
+/// `Global*` delegates: it claims support for exactly [unsupported] and
+/// serves [replacement] in their place.
+class _WidgetsFallbackDelegate extends LocalizationsDelegate {
+ const _WidgetsFallbackDelegate({
+ required this.loadWith,
+ required this.unsupported,
+ required this.replacement,
+ });
+
+ final Future Function(Locale locale) loadWith;
+ final List unsupported;
+ final Locale replacement;
+
+ @override
+ bool isSupported(Locale locale) => unsupported.contains(locale);
+
+ @override
+ Future load(Locale locale) => loadWith(replacement);
+
+ @override
+ bool shouldReload(_WidgetsFallbackDelegate old) =>
+ old.unsupported != unsupported || old.replacement != replacement;
+
+ @override
+ String toString() => 'WidgetsFallbackDelegate($unsupported → $replacement)';
+}
+
bool _isBareChinese(Locale locale) =>
locale.languageCode == 'zh' &&
locale.scriptCode == null &&
diff --git a/lib/features/changelog/presentation/pages/version_notes_page.dart b/lib/features/changelog/presentation/pages/version_notes_page.dart
index 8cea043cb..54c4fe765 100644
--- a/lib/features/changelog/presentation/pages/version_notes_page.dart
+++ b/lib/features/changelog/presentation/pages/version_notes_page.dart
@@ -19,11 +19,13 @@ import 'package:dpip/features/changelog/domain/update_check.dart';
import 'package:dpip/features/changelog/presentation/widgets/release_contributors.dart';
import 'package:dpip/features/changelog/presentation/widgets/release_note_markdown.dart';
import 'package:dpip/l10n/gen/app_localizations.dart';
+import 'package:dpip/shared/navigation/app_routes.dart';
import 'package:dpip/shared/navigation/refresh_on_appear.dart';
import 'package:dpip/shared/widgets/async_view.dart';
import 'package:dpip/shared/widgets/empty_view.dart';
import 'package:flutter/material.dart';
import 'package:flutter_markdown_plus/flutter_markdown_plus.dart';
+import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
@@ -63,7 +65,17 @@ class VersionNotesPage extends StatelessWidget {
message: l10n.moreVersionNotesEmpty,
),
builder: (context, notes) {
- final note = notes.where((n) => _isCurrent(n, label)).firstOrNull;
+ // A build no published release names (a local/dev label, or a
+ // snapshot newer than the fetched page) falls back to the newest
+ // note — same rule the version card's avatars use, so the page is
+ // never bare once any note has been fetched.
+ final note =
+ notes.where((n) => _isCurrent(n, label)).firstOrNull ??
+ (notes.isEmpty
+ ? null
+ : notes.reduce(
+ (a, b) => a.publishedAt.isAfter(b.publishedAt) ? a : b,
+ ));
if (note == null) {
return EmptyView(
icon: Icons.question_mark_outlined,
@@ -81,6 +93,12 @@ class VersionNotesPage extends StatelessWidget {
AppSpacing.xl + MediaQuery.paddingOf(context).bottom,
),
children: [
+ // The version's own story, one level further in: the train's
+ // key highlights, named for the release (e.g. 26.1 重點整理)
+ // rather than this build. Sits right under the app bar so the
+ // reader finds the summary first, before this build's note.
+ _HighlightsEntry(train: AppBuild.train),
+ const SizedBox(height: AppSpacing.md),
_Header(note: note, isStable: stable),
const SizedBox(height: AppSpacing.md),
_Body(
@@ -124,31 +142,51 @@ class _Header extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Chip(
- avatar: Icon(
- isStable ? Icons.verified_outlined : Icons.science_outlined,
- size: 18,
- color: Colors.white,
- ),
- label: Text(
- isStable ? l10n.changelogTypeStable : l10n.changelogTypePrerelease,
- ),
- backgroundColor: typeColor,
- labelStyle: theme.textTheme.labelMedium?.copyWith(
- color: Colors.white,
- fontWeight: FontWeight.w700,
- ),
- side: const BorderSide(color: Colors.transparent),
- visualDensity: VisualDensity.compact,
- ),
- const SizedBox(height: AppSpacing.sm),
- Text(
- title,
- style: theme.textTheme.headlineSmall?.copyWith(
- fontWeight: FontWeight.w800,
- color: colors.onSurface,
- letterSpacing: -0.3,
- ),
+ // Same pairing as the changelog card: the name and its type badge sit
+ // together on one line, badge hugging the text — a tinted wash with a
+ // hairline of the same hue, not a solid fill.
+ Wrap(
+ spacing: AppSpacing.sm,
+ runSpacing: AppSpacing.xs,
+ crossAxisAlignment: WrapCrossAlignment.center,
+ children: [
+ // The same type icon the changelog card leads with: a flask for a
+ // snapshot, a verified badge for a release.
+ Icon(
+ isStable ? Icons.verified_outlined : Icons.science_outlined,
+ size: 22,
+ color: typeColor,
+ ),
+ Text(
+ title,
+ style: theme.textTheme.headlineSmall?.copyWith(
+ fontWeight: FontWeight.w800,
+ color: colors.onSurface,
+ letterSpacing: -0.3,
+ ),
+ ),
+ Container(
+ padding: const EdgeInsets.symmetric(
+ horizontal: AppSpacing.sm,
+ vertical: 2,
+ ),
+ decoration: BoxDecoration(
+ color: typeColor.withValues(alpha: 0.14),
+ borderRadius: BorderRadius.circular(AppRadius.sm),
+ border: Border.all(color: typeColor.withValues(alpha: 0.45)),
+ ),
+ child: Text(
+ isStable
+ ? l10n.changelogTypeStable
+ : l10n.changelogTypePrerelease,
+ style: theme.textTheme.labelSmall?.copyWith(
+ fontWeight: FontWeight.w700,
+ color: typeColor,
+ letterSpacing: 0.2,
+ ),
+ ),
+ ),
+ ],
),
const SizedBox(height: AppSpacing.xs),
Text(
@@ -162,6 +200,82 @@ class _Header extends StatelessWidget {
}
}
+/// Entry card to the train's key-highlights deck (release highlights), one
+/// level further in from this build's own note. Label carries the train
+/// number so the reader sees where the note they just read fits.
+class _HighlightsEntry extends StatelessWidget {
+ const _HighlightsEntry({required this.train});
+
+ final String train;
+
+ @override
+ Widget build(BuildContext context) {
+ final l10n = AppLocalizations.of(context);
+ final theme = Theme.of(context);
+ final colors = theme.colorScheme;
+ return Material(
+ color: colors.primaryContainer.withValues(alpha: 0.35),
+ shape: RoundedRectangleBorder(
+ borderRadius: AppRadius.medium,
+ side: BorderSide(color: colors.primary.withValues(alpha: 0.35)),
+ ),
+ clipBehavior: Clip.antiAlias,
+ child: InkWell(
+ onTap: () => context.pushNamed(AppRoutes.releaseHighlights),
+ child: Padding(
+ padding: const EdgeInsets.fromLTRB(
+ AppSpacing.lg,
+ AppSpacing.md,
+ AppSpacing.md,
+ AppSpacing.md,
+ ),
+ child: Row(
+ children: [
+ Container(
+ width: 40,
+ height: 40,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ color: colors.primary.withValues(alpha: 0.14),
+ ),
+ child: Icon(
+ Icons.auto_awesome,
+ size: 22,
+ color: colors.primary,
+ ),
+ ),
+ const SizedBox(width: AppSpacing.md),
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ l10n.releaseHighlightsTitle(train),
+ style: theme.textTheme.titleMedium?.copyWith(
+ fontWeight: FontWeight.w800,
+ letterSpacing: -0.2,
+ ),
+ ),
+ const SizedBox(height: 2),
+ Text(
+ l10n.moreVersionNotesHighlightsSubtitle,
+ style: theme.textTheme.bodySmall?.copyWith(
+ color: colors.onSurfaceVariant,
+ ),
+ ),
+ ],
+ ),
+ ),
+ const SizedBox(width: AppSpacing.xs),
+ Icon(Icons.chevron_right, color: colors.onSurfaceVariant),
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
+
/// The release note body, rendered like the changelog's expanded tile so a
/// user sees the same typography in both places, with the contributor strip
/// below.
diff --git a/lib/features/data/presentation/pages/data_page.dart b/lib/features/data/presentation/pages/data_page.dart
index 9ba30d8e3..ba047cd9b 100644
--- a/lib/features/data/presentation/pages/data_page.dart
+++ b/lib/features/data/presentation/pages/data_page.dart
@@ -50,128 +50,130 @@ class DataPage extends StatelessWidget {
final l10n = AppLocalizations.of(context);
final colors = Theme.of(context).colorScheme;
return Scaffold(
- appBar: AppBar(title: Text(l10n.navData)),
- body: ListView(
- padding: EdgeInsets.only(
- top: AppSpacing.sm,
- bottom: AppSpacing.xl + MediaQuery.paddingOf(context).bottom,
- ),
- children: [
- SectionHeader(l10n.dataSectionSeismic),
- Padding(
- padding: const EdgeInsets.fromLTRB(
- AppSpacing.lg,
- 0,
- AppSpacing.lg,
- AppSpacing.sm,
- ),
- child: _SeismicCard(
- icon: Icons.monitor_heart_outlined,
- title: l10n.dataEarthquakeSubtitle,
- onTap: () => context.pushNamed(AppRoutes.earthquake),
- ),
+ body: SafeArea(
+ bottom: false,
+ child: ListView(
+ padding: EdgeInsets.only(
+ top: AppSpacing.sm,
+ bottom: AppSpacing.xl + MediaQuery.paddingOf(context).bottom,
),
- SectionHeader(l10n.dataSectionWeather),
- GridView.count(
- crossAxisCount: 2,
- shrinkWrap: true,
- physics: const NeverScrollableScrollPhysics(),
- padding: const EdgeInsets.fromLTRB(
- AppSpacing.lg,
- 0,
- AppSpacing.lg,
- AppSpacing.sm,
+ children: [
+ SectionHeader(l10n.dataSectionSeismic),
+ Padding(
+ padding: const EdgeInsets.fromLTRB(
+ AppSpacing.lg,
+ 0,
+ AppSpacing.lg,
+ AppSpacing.sm,
+ ),
+ child: _SeismicCard(
+ icon: Icons.monitor_heart_outlined,
+ title: l10n.dataEarthquakeSubtitle,
+ onTap: () => context.pushNamed(AppRoutes.earthquake),
+ ),
),
- crossAxisSpacing: AppSpacing.sm,
- mainAxisSpacing: AppSpacing.sm,
- // Wide and short: icon left, label right, one glance per tile.
- childAspectRatio: 2.4,
- children: [
- for (final (tab, icon) in _weatherRankingEntries)
- _RankingGridTile(
- icon: icon,
- title: _weatherRankingLabel(l10n, tab),
- accent: switch (tab) {
- 'rain' => colors.primary,
- 'temperature' => colors.tertiary,
- _ => colors.secondary,
- },
- onTap: () => context.pushNamed(
- AppRoutes.weatherRanking,
- queryParameters: {'tab': tab},
+ SectionHeader(l10n.dataSectionWeather),
+ GridView.count(
+ crossAxisCount: 2,
+ shrinkWrap: true,
+ physics: const NeverScrollableScrollPhysics(),
+ padding: const EdgeInsets.fromLTRB(
+ AppSpacing.lg,
+ 0,
+ AppSpacing.lg,
+ AppSpacing.sm,
+ ),
+ crossAxisSpacing: AppSpacing.sm,
+ mainAxisSpacing: AppSpacing.sm,
+ // Wide and short: icon left, label right, one glance per tile.
+ childAspectRatio: 2.4,
+ children: [
+ for (final (tab, icon) in _weatherRankingEntries)
+ _RankingGridTile(
+ icon: icon,
+ title: _weatherRankingLabel(l10n, tab),
+ accent: switch (tab) {
+ 'rain' => colors.primary,
+ 'temperature' => colors.tertiary,
+ _ => colors.secondary,
+ },
+ onTap: () => context.pushNamed(
+ AppRoutes.weatherRanking,
+ queryParameters: {'tab': tab},
+ ),
),
- ),
- ],
- ),
- SectionHeader(l10n.dataSectionAstronomy),
- GridView.count(
- crossAxisCount: 2,
- shrinkWrap: true,
- physics: const NeverScrollableScrollPhysics(),
- padding: const EdgeInsets.fromLTRB(
- AppSpacing.lg,
- 0,
- AppSpacing.lg,
- AppSpacing.sm,
+ ],
),
- crossAxisSpacing: AppSpacing.sm,
- mainAxisSpacing: AppSpacing.sm,
- childAspectRatio: 2.4,
- children: [
- for (final (route, icon, label, accent)
- in <(String, IconData, String, Color)>[
- (
- AppRoutes.moon,
- Icons.nightlight_outlined,
- l10n.moonTitle,
- colors.tertiary,
- ),
- (
- AppRoutes.sun,
- Icons.wb_sunny_outlined,
- l10n.sunTitle,
- colors.primary,
- ),
- (
- AppRoutes.planets,
- Icons.blur_circular_outlined,
- l10n.planetsTitle,
- colors.secondary,
- ),
- (
- AppRoutes.tonight,
- Icons.dark_mode_outlined,
- l10n.tonightTitle,
- colors.primary,
- ),
- (
- AppRoutes.skyChart,
- Icons.auto_awesome_outlined,
- l10n.skyChartTitle,
- colors.tertiary,
- ),
- (
- AppRoutes.almanac,
- Icons.calendar_month_outlined,
- l10n.almanacTitle,
- colors.secondary,
- ),
- (
- AppRoutes.tide,
- Icons.waves_outlined,
- l10n.tideTitle,
- colors.primary,
- ),
- ])
- _RankingGridTile(
- icon: icon,
- title: label,
- accent: accent,
- onTap: () => context.pushNamed(route),
- ),
- ],
- ),
- ],
+ SectionHeader(l10n.dataSectionAstronomy),
+ GridView.count(
+ crossAxisCount: 2,
+ shrinkWrap: true,
+ physics: const NeverScrollableScrollPhysics(),
+ padding: const EdgeInsets.fromLTRB(
+ AppSpacing.lg,
+ 0,
+ AppSpacing.lg,
+ AppSpacing.sm,
+ ),
+ crossAxisSpacing: AppSpacing.sm,
+ mainAxisSpacing: AppSpacing.sm,
+ childAspectRatio: 2.4,
+ children: [
+ for (final (route, icon, label, accent)
+ in <(String, IconData, String, Color)>[
+ (
+ AppRoutes.moon,
+ Icons.nightlight_outlined,
+ l10n.moonTitle,
+ colors.tertiary,
+ ),
+ (
+ AppRoutes.sun,
+ Icons.wb_sunny_outlined,
+ l10n.sunTitle,
+ colors.primary,
+ ),
+ (
+ AppRoutes.planets,
+ Icons.blur_circular_outlined,
+ l10n.planetsTitle,
+ colors.secondary,
+ ),
+ (
+ AppRoutes.tonight,
+ Icons.dark_mode_outlined,
+ l10n.tonightTitle,
+ colors.primary,
+ ),
+ (
+ AppRoutes.skyChart,
+ Icons.auto_awesome_outlined,
+ l10n.skyChartTitle,
+ colors.tertiary,
+ ),
+ (
+ AppRoutes.almanac,
+ Icons.calendar_month_outlined,
+ l10n.almanacTitle,
+ colors.secondary,
+ ),
+ (
+ AppRoutes.tide,
+ Icons.waves_outlined,
+ l10n.tideTitle,
+ colors.primary,
+ ),
+ ])
+ _RankingGridTile(
+ icon: icon,
+ title: label,
+ accent: accent,
+ onTap: () => context.pushNamed(route),
+ ),
+ ],
+ ),
+ ],
+ ),
),
);
}
diff --git a/lib/features/map/presentation/layers/mesh_node_layer.dart b/lib/features/map/presentation/layers/mesh_node_layer.dart
index 064e489ca..9b298581f 100644
--- a/lib/features/map/presentation/layers/mesh_node_layer.dart
+++ b/lib/features/map/presentation/layers/mesh_node_layer.dart
@@ -18,7 +18,6 @@ import 'package:dpip/core/meshtastic/domain/meshtastic_service.dart';
import 'package:dpip/core/meshtastic/mesh_node_store.dart';
import 'package:dpip/features/map/presentation/widgets/mesh_node_sheet.dart';
import 'package:dpip/l10n/gen/app_localizations.dart';
-import 'package:dpip/shared/map/map_terrain_toggle.dart';
import 'package:dpip/shared/map/map_town_labels.dart';
import 'package:dpip/shared/widgets/map_chip_button.dart';
import 'package:dpip/shared/widgets/map_color_legend.dart';
@@ -844,6 +843,16 @@ class _MeshNodeMenu extends StatelessWidget {
menuChildren: [
MapMenuScrollView(
children: [
+ // The shared map section stays first in every settings list;
+ // OSM is the common action and should never be buried below a
+ // layer-specific filter.
+ MapBasemapControlRows(
+ showTownLabels: showTownLabels,
+ onShowTownLabelsChanged: onShowTownLabelsChanged,
+ showTerrain: showTerrain,
+ onShowTerrainChanged: onShowTerrainChanged,
+ ),
+ const MapMenuDivider(),
SectionHeader(l10n.meshtasticNodes),
MapMenuToggleRow(
selected: excludeMqtt,
@@ -855,18 +864,6 @@ class _MeshNodeMenu extends StatelessWidget {
tooltip: l10n.meshtasticExcludeMqttSubtitle,
onTap: () => onExcludeMqttChanged(!excludeMqtt),
),
- const MapMenuDivider(),
- // The shared base-map rows, not copies of them: this menu
- // replaces the standalone base-map chip, so the toggles have
- // to be the same ones the user finds on every other layer.
- MapTownLabelsRow(
- showTownLabels: showTownLabels,
- onShowTownLabelsChanged: onShowTownLabelsChanged,
- ),
- MapTerrainRow(
- showTerrain: showTerrain,
- onShowTerrainChanged: onShowTerrainChanged,
- ),
],
),
],
diff --git a/lib/features/map/presentation/layers/rain_layer.dart b/lib/features/map/presentation/layers/rain_layer.dart
index 402fc21f0..2b6321cd3 100644
--- a/lib/features/map/presentation/layers/rain_layer.dart
+++ b/lib/features/map/presentation/layers/rain_layer.dart
@@ -8,7 +8,6 @@ import 'package:dpip/features/weather/domain/rain_interval.dart';
import 'package:dpip/features/weather/domain/rain_snapshot.dart';
import 'package:dpip/features/weather/domain/rain_trend.dart';
import 'package:dpip/l10n/gen/app_localizations.dart';
-import 'package:dpip/shared/map/map_terrain_toggle.dart';
import 'package:dpip/shared/map/map_town_labels.dart';
import 'package:dpip/shared/widgets/map_chip_button.dart';
import 'package:dpip/shared/widgets/section_header.dart';
@@ -165,6 +164,13 @@ class RainMapLayer
menuChildren: [
MapMenuScrollView(
children: [
+ MapBasemapControlRows(
+ showTownLabels: showTownLabels,
+ onShowTownLabelsChanged: onShowTownLabelsChanged,
+ showTerrain: showTerrain,
+ onShowTerrainChanged: onShowTerrainChanged,
+ ),
+ const MapMenuDivider(),
SectionHeader(l10n.rainIntervalSection),
for (final option in RainInterval.values)
MenuItemButton(
@@ -174,16 +180,6 @@ class RainMapLayer
: null,
child: Text(option.label(l10n)),
),
- const MapMenuDivider(),
- SectionHeader(l10n.mapOverlaySectionMap),
- MapTownLabelsRow(
- showTownLabels: showTownLabels,
- onShowTownLabelsChanged: onShowTownLabelsChanged,
- ),
- MapTerrainRow(
- showTerrain: showTerrain,
- onShowTerrainChanged: onShowTerrainChanged,
- ),
],
),
],
diff --git a/lib/features/map/presentation/pages/map_page.dart b/lib/features/map/presentation/pages/map_page.dart
index dee83b4db..0f623caf4 100644
--- a/lib/features/map/presentation/pages/map_page.dart
+++ b/lib/features/map/presentation/pages/map_page.dart
@@ -118,6 +118,7 @@ class _MapPageState extends State {
key: ValueKey(initial.id),
layers: _layers,
initialLayerId: initial.id,
+ initialOsmEnabled: initial == DefaultMapLayer.dpm,
tabIndex: MapPage.tabIndex,
);
}
diff --git a/lib/features/map/presentation/widgets/disaster_map_overlay_menu.dart b/lib/features/map/presentation/widgets/disaster_map_overlay_menu.dart
index 93565da52..5a1517cc7 100644
--- a/lib/features/map/presentation/widgets/disaster_map_overlay_menu.dart
+++ b/lib/features/map/presentation/widgets/disaster_map_overlay_menu.dart
@@ -6,7 +6,6 @@ import 'package:dpip/app/theme/app_spacing.dart';
import 'package:dpip/features/map/presentation/layers/disaster_map_layer.dart';
import 'package:dpip/l10n/gen/app_localizations.dart';
import 'package:dpip/shared/color_hex.dart';
-import 'package:dpip/shared/map/map_terrain_toggle.dart';
import 'package:dpip/shared/map/map_town_labels.dart';
import 'package:dpip/shared/widgets/map_chip_button.dart';
import 'package:dpip/shared/widgets/section_header.dart';
@@ -66,6 +65,13 @@ class DisasterMapOverlayMenu extends StatelessWidget {
menuChildren: [
MapMenuScrollView(
children: [
+ MapBasemapControlRows(
+ showTownLabels: showTownLabels,
+ onShowTownLabelsChanged: onShowTownLabelsChanged,
+ showTerrain: showTerrain,
+ onShowTerrainChanged: onShowTerrainChanged,
+ ),
+ const MapMenuDivider(),
SectionHeader(l10n.disasterMapOverlaySectionLayers),
for (final sub in layer.subLayers)
_ToggleRow(
@@ -77,16 +83,6 @@ class DisasterMapOverlayMenu extends StatelessWidget {
onTap: () =>
layer.setSubLayerVisible(sub, !sub.visible.value),
),
- const MapMenuDivider(),
- SectionHeader(l10n.mapOverlaySectionMap),
- MapTownLabelsRow(
- showTownLabels: showTownLabels,
- onShowTownLabelsChanged: onShowTownLabelsChanged,
- ),
- MapTerrainRow(
- showTerrain: showTerrain,
- onShowTerrainChanged: onShowTerrainChanged,
- ),
],
),
],
diff --git a/lib/features/map/presentation/widgets/forecast_overlay_menu.dart b/lib/features/map/presentation/widgets/forecast_overlay_menu.dart
index 000be2612..c3b828e33 100644
--- a/lib/features/map/presentation/widgets/forecast_overlay_menu.dart
+++ b/lib/features/map/presentation/widgets/forecast_overlay_menu.dart
@@ -5,7 +5,6 @@ library;
import 'package:dpip/features/map/presentation/layers/admin_outline_chrome.dart';
import 'package:dpip/l10n/gen/app_localizations.dart';
-import 'package:dpip/shared/map/map_terrain_toggle.dart';
import 'package:dpip/shared/map/map_town_labels.dart';
import 'package:dpip/shared/widgets/map_chip_button.dart';
import 'package:dpip/shared/widgets/map_menu_toggle_row.dart';
@@ -76,6 +75,13 @@ class ForecastOverlayMenu extends StatelessWidget {
menuChildren: [
MapMenuScrollView(
children: [
+ MapBasemapControlRows(
+ showTownLabels: showTownLabels,
+ onShowTownLabelsChanged: onShowTownLabelsChanged,
+ showTerrain: showTerrain,
+ onShowTerrainChanged: onShowTerrainChanged,
+ ),
+ const MapMenuDivider(),
SectionHeader(l10n.mapOverlaySectionReference),
MapMenuToggleRow(
selected: showGlobal,
@@ -101,16 +107,6 @@ class ForecastOverlayMenu extends StatelessWidget {
tooltip: l10n.windForecastTownOutlineHint,
onTap: () => layer.setShowTownOutline(!showTown),
),
- const MapMenuDivider(),
- SectionHeader(l10n.mapOverlaySectionMap),
- MapTownLabelsRow(
- showTownLabels: showTownLabels,
- onShowTownLabelsChanged: onShowTownLabelsChanged,
- ),
- MapTerrainRow(
- showTerrain: showTerrain,
- onShowTerrainChanged: onShowTerrainChanged,
- ),
],
),
],
diff --git a/lib/features/map/presentation/widgets/satellite_style_menu.dart b/lib/features/map/presentation/widgets/satellite_style_menu.dart
index 3a2b403b1..4b1703b6f 100644
--- a/lib/features/map/presentation/widgets/satellite_style_menu.dart
+++ b/lib/features/map/presentation/widgets/satellite_style_menu.dart
@@ -6,7 +6,6 @@ import 'package:dpip/app/theme/app_spacing.dart';
import 'package:dpip/features/map/presentation/layers/satellite_layer.dart';
import 'package:dpip/features/weather/domain/satellite_channel.dart';
import 'package:dpip/l10n/gen/app_localizations.dart';
-import 'package:dpip/shared/map/map_terrain_toggle.dart';
import 'package:dpip/shared/map/map_town_labels.dart';
import 'package:dpip/shared/widgets/map_chip_button.dart';
import 'package:dpip/shared/widgets/map_menu_toggle_row.dart';
@@ -78,6 +77,13 @@ class SatelliteStyleMenu extends StatelessWidget {
menuChildren: [
MapMenuScrollView(
children: [
+ MapBasemapControlRows(
+ showTownLabels: showTownLabels,
+ onShowTownLabelsChanged: onShowTownLabelsChanged,
+ showTerrain: showTerrain,
+ onShowTerrainChanged: onShowTerrainChanged,
+ ),
+ const MapMenuDivider(),
SectionHeader(l10n.mapLayerStyleSection),
_StyleRow(
selected: style == SatelliteStyle.gray,
@@ -119,16 +125,6 @@ class SatelliteStyleMenu extends StatelessWidget {
tooltip: l10n.radarGlobalOutlineHint,
onTap: () => layer.setShowGlobalOutline(!showGlobal),
),
- const MapMenuDivider(),
- SectionHeader(l10n.mapOverlaySectionMap),
- MapTownLabelsRow(
- showTownLabels: showTownLabels,
- onShowTownLabelsChanged: onShowTownLabelsChanged,
- ),
- MapTerrainRow(
- showTerrain: showTerrain,
- onShowTerrainChanged: onShowTerrainChanged,
- ),
],
),
],
@@ -188,6 +184,13 @@ class SatelliteReferenceMenu extends StatelessWidget {
menuChildren: [
MapMenuScrollView(
children: [
+ MapBasemapControlRows(
+ showTownLabels: showTownLabels,
+ onShowTownLabelsChanged: onShowTownLabelsChanged,
+ showTerrain: showTerrain,
+ onShowTerrainChanged: onShowTerrainChanged,
+ ),
+ const MapMenuDivider(),
SectionHeader(l10n.mapOverlaySectionReference),
MapMenuToggleRow(
selected: showGlobal,
@@ -197,16 +200,6 @@ class SatelliteReferenceMenu extends StatelessWidget {
tooltip: l10n.radarGlobalOutlineHint,
onTap: () => layer.setShowGlobalOutline(!showGlobal),
),
- const MapMenuDivider(),
- SectionHeader(l10n.mapOverlaySectionMap),
- MapTownLabelsRow(
- showTownLabels: showTownLabels,
- onShowTownLabelsChanged: onShowTownLabelsChanged,
- ),
- MapTerrainRow(
- showTerrain: showTerrain,
- onShowTerrainChanged: onShowTerrainChanged,
- ),
],
),
],
diff --git a/lib/features/map/presentation/widgets/scan_range_overlay_menu.dart b/lib/features/map/presentation/widgets/scan_range_overlay_menu.dart
index 2e7e84b76..0feda1bad 100644
--- a/lib/features/map/presentation/widgets/scan_range_overlay_menu.dart
+++ b/lib/features/map/presentation/widgets/scan_range_overlay_menu.dart
@@ -5,7 +5,6 @@ library;
import 'package:dpip/features/map/presentation/layers/scan_range_overlay_chrome.dart';
import 'package:dpip/l10n/gen/app_localizations.dart';
-import 'package:dpip/shared/map/map_terrain_toggle.dart';
import 'package:dpip/shared/map/map_town_labels.dart';
import 'package:dpip/shared/widgets/map_chip_button.dart';
import 'package:dpip/shared/widgets/map_menu_toggle_row.dart';
@@ -80,6 +79,13 @@ class ScanRangeOverlayMenu extends StatelessWidget {
menuChildren: [
MapMenuScrollView(
children: [
+ MapBasemapControlRows(
+ showTownLabels: showTownLabels,
+ onShowTownLabelsChanged: onShowTownLabelsChanged,
+ showTerrain: showTerrain,
+ onShowTerrainChanged: onShowTerrainChanged,
+ ),
+ const MapMenuDivider(),
SectionHeader(l10n.mapOverlaySectionReference),
MapMenuToggleRow(
selected: showGlobal,
@@ -113,16 +119,6 @@ class ScanRangeOverlayMenu extends StatelessWidget {
tooltip: l10n.radarTownOutlineSubtitle,
onTap: () => layer.setShowTownOutline(!showTown),
),
- const MapMenuDivider(),
- SectionHeader(l10n.mapOverlaySectionMap),
- MapTownLabelsRow(
- showTownLabels: showTownLabels,
- onShowTownLabelsChanged: onShowTownLabelsChanged,
- ),
- MapTerrainRow(
- showTerrain: showTerrain,
- onShowTerrainChanged: onShowTerrainChanged,
- ),
],
),
],
diff --git a/lib/features/map/presentation/widgets/typhoon_overlay_menu.dart b/lib/features/map/presentation/widgets/typhoon_overlay_menu.dart
index d608be23b..1a095a183 100644
--- a/lib/features/map/presentation/widgets/typhoon_overlay_menu.dart
+++ b/lib/features/map/presentation/widgets/typhoon_overlay_menu.dart
@@ -7,7 +7,6 @@ import 'package:dpip/features/map/presentation/layers/typhoon_layer.dart';
import 'package:dpip/features/map/presentation/layers/typhoon_storm_band.dart';
import 'package:dpip/features/map/presentation/layers/typhoon_weather_overlay.dart';
import 'package:dpip/l10n/gen/app_localizations.dart';
-import 'package:dpip/shared/map/map_terrain_toggle.dart';
import 'package:dpip/shared/map/map_town_labels.dart';
import 'package:dpip/shared/widgets/map_chip_button.dart';
import 'package:dpip/shared/widgets/map_menu_toggle_row.dart';
@@ -96,6 +95,13 @@ class TyphoonOverlayMenu extends StatelessWidget {
menuChildren: [
MapMenuScrollView(
children: [
+ MapBasemapControlRows(
+ showTownLabels: showTownLabels,
+ onShowTownLabelsChanged: onShowTownLabelsChanged,
+ showTerrain: showTerrain,
+ onShowTerrainChanged: onShowTerrainChanged,
+ ),
+ const MapMenuDivider(),
SectionHeader(l10n.typhoonOverlaySectionStorm),
_StormBandRow(
selected: band == TyphoonStormBand.level7,
@@ -195,16 +201,6 @@ class TyphoonOverlayMenu extends StatelessWidget {
tooltip: l10n.typhoonOverlayWarningTooltip,
onTap: () => layer.setShowWarningAreas(!showWarn),
),
- const MapMenuDivider(),
- SectionHeader(l10n.mapOverlaySectionMap),
- MapTownLabelsRow(
- showTownLabels: showTownLabels,
- onShowTownLabelsChanged: onShowTownLabelsChanged,
- ),
- MapTerrainRow(
- showTerrain: showTerrain,
- onShowTerrainChanged: onShowTerrainChanged,
- ),
],
),
],
diff --git a/lib/features/more/domain/developer_note.dart b/lib/features/more/domain/developer_note.dart
new file mode 100644
index 000000000..95c3a232e
--- /dev/null
+++ b/lib/features/more/domain/developer_note.dart
@@ -0,0 +1,136 @@
+/// The developer note card's copy, in every written language.
+///
+/// Kept in Dart (not ARB) on purpose: the note tracks live incidents and
+/// changes faster than a release cycle — by the time an ARB change round-
+/// trips through gen-l10n, translation review and a store build, the note is
+/// already history. A raw Dart map can be edited and shipped in one commit.
+/// It is also why this card lives outside the presentation layer: the l10n
+/// gate scans [AppLocalizations]-routed files; a moving target here would
+/// churn the generated delegates for nothing.
+class DeveloperNote {
+ const DeveloperNote({required this.title, required this.body});
+
+ final String title;
+ final String body;
+}
+
+/// The note per locale, keyed by `Locale.toString()` (`zh_TW`, `en`, …).
+/// Home-locale copy first, so the fallback below is a direct lookup.
+const Map _developerNotes = {
+ 'zh_TW': DeveloperNote(
+ title: '開發者的話',
+ body:
+ '我們注意到 Android 版本的 DPIP 還有不少問題,我們正在調查原因,'
+ '將盡快修正並發布更新。若有其他問題可以至 Discord 社群回報,'
+ '我們願意傾聽,但請不要直接至商店負評,直接負評的溝通效率很差,'
+ '且對我們的打擊很大。',
+ ),
+ 'zh': DeveloperNote(
+ title: '開發者的話',
+ body:
+ '我們注意到 Android 版本的 DPIP 還有不少問題,我們正在調查原因,'
+ '將盡快修正並發布更新。若有其他問題可以至 Discord 社群回報,'
+ '我們願意傾聽,但請不要直接至商店負評,直接負評的溝通效率很差,'
+ '且對我們的打擊很大。',
+ ),
+ 'zh_Hant_HK': DeveloperNote(
+ title: '開發者的話',
+ body:
+ '我們留意到 Android 版本的 DPIP 還有不少問題,我們正在調查原因,'
+ '會盡快修正並發布更新。如有其他問題可以到 Discord 社群回報,'
+ '我們願意傾聽,但請不要直接在商店留負評,直接負評的溝通效率很低,'
+ '對我們的打擊也很大。',
+ ),
+ 'zh_Hans': DeveloperNote(
+ title: '开发者的话',
+ body:
+ '我们注意到 Android 版本的 DPIP 还有不少问题,我们正在调查原因,'
+ '将尽快修复并发布更新。如有其他问题可以在 Discord 社区反馈,'
+ '我们愿意倾听,但请不要直接在商店打差评,差评的沟通效率很低,'
+ '对我们打击也很大。',
+ ),
+ 'yue': DeveloperNote(
+ title: '開發者嘅話',
+ body:
+ '我哋留意到 Android 版嘅 DPIP 仲有唔少問題,我哋而家正在調查原因,'
+ '會盡快修正同發布更新。如果仲有其他問題,可以去 Discord 社群回報,'
+ '我哋願意傾聽,但請唔好直接去商店留負評,負評嘅溝通效率好差,'
+ '對我哋打擊好大。',
+ ),
+ 'en': DeveloperNote(
+ title: 'A word from the developers',
+ body:
+ 'We know the Android version of DPIP still has a number of issues. '
+ 'We are investigating the causes and will fix them and ship an update '
+ 'as soon as possible. For anything else, please report it in our '
+ 'Discord community — we are listening — but please do not leave a '
+ 'negative review on the store: reviews are a poor channel for '
+ 'feedback, and they hurt us a lot.',
+ ),
+ 'ja': DeveloperNote(
+ title: '開発者からのお知らせ',
+ body:
+ 'Android 版の DPIP にはまだ多くの問題があることを認識しています。'
+ '原因を調査中で、できるだけ早く修正しアップデートをリリースします。'
+ 'その他の問題があれば Discord コミュニティまでご報告ください。'
+ '拝聴いたしますが、ストアへの低評価だけはご遠慮ください。'
+ '低評価はフィードバックの伝達効率が悪く、私たちにとって大きな'
+ '打撃となります。',
+ ),
+ 'ko': DeveloperNote(
+ title: '개발자의 말',
+ body:
+ 'Android 버전의 DPIP에 아직 적지 않은 문제가 있음을 알고 있습니다. '
+ '원인을 조사 중이며, 최대한 빨리 수정하고 업데이트를 출시하겠습니다. '
+ '다른 문제가 있으면 Discord 커뮤니티에 알려 주세요. 저희가 귀 '
+ '기울여 듣겠습니다. 다만 스토어에 낮은 평점을 남기는 것은 삼가 '
+ '주세요. 낮은 평점은 소통 효율이 매우 낮고, 저희에게 큰 타격이 됩니다.',
+ ),
+ 'th': DeveloperNote(
+ title: 'ข้อความจากทีมพัฒนา',
+ body:
+ 'เราทราบว่าแอป DPIP เวอร์ชัน Android ยังมีปัญหาอีกหลายจุด '
+ 'เรากำลังหาสาเหตุและจะรีบแก้ไขพร้อมปล่อยอัปเดตโดยเร็วที่สุด '
+ 'หากมีปัญหาอื่น ๆ แจ้งได้ที่ชุมชน Discord เรายินดีรับฟัง '
+ 'แต่ขออย่าโพสต์รีวิวไม่ดีที่หน้าร้านแอป เพราะรีวิวไม่ดีสื่อสารได้ไม่ตรงจุด '
+ 'และกระทบเราอย่างหนัก',
+ ),
+ 'vi': DeveloperNote(
+ title: 'Lời từ đội ngũ phát triển',
+ body:
+ 'Chúng tôi biết phiên bản DPIP trên Android vẫn còn khá nhiều vấn đề. '
+ 'Chúng tôi đang điều tra nguyên nhân và sẽ sớm khắc phục cùng phát '
+ 'hành bản cập nhật. Nếu gặp vấn đề khác, bạn có thể phản ánh tại cộng '
+ 'đồng Discord — chúng tôi sẵn sàng lắng nghe — nhưng mong bạn đừng để '
+ 'đánh giá tiêu cực trên cửa hàng ứng dụng, vì đánh giá tiêu cực không '
+ 'phải kênh trao đổi hiệu quả và ảnh hưởng rất lớn đến chúng tôi.',
+ ),
+ 'id': DeveloperNote(
+ title: 'Kata dari pengembang',
+ body:
+ 'Kami menyadari DPIP versi Android masih memiliki cukup banyak '
+ 'masalah. Kami sedang menyelidiki penyebabnya dan akan segera '
+ 'memperbaikinya serta merilis pembaruan. Jika ada masalah lain, '
+ 'silakan laporkan ke komunitas Discord — kami siap mendengarkan — '
+ 'tetapi mohon jangan memberi ulasan buruk di toko aplikasi, karena '
+ 'ulasan buruk bukan sarana komunikasi yang efektif dan sangat '
+ 'berdampak bagi kami.',
+ ),
+ 'fil': DeveloperNote(
+ title: 'Mensahe mula sa mga developer',
+ body:
+ 'Alam namin na may ilan pang problema ang bersyon ng DPIP sa Android. '
+ 'Iniimbestigahan namin ang dahilan at aayusin namin ito sa lalong '
+ 'madaling panahon, kasabay ng paglabas ng update. Kung may iba pang '
+ 'problema, maaari kayong mag-ulat sa Discord community — handa kaming '
+ 'makinig — ngunit mangyaring huwag mag-iwan ng negatibong review sa '
+ 'app store, dahil hindi epektibong paraan ng pakikipag-ugnayan ang '
+ 'negatibong review at malaki ang epekto nito sa amin.',
+ ),
+};
+
+/// The note for [locale], keyed by `Locale.toString()` ('zh_TW', 'en', …) —
+/// an exact match first, then the home locale's copy (zh_TW), the same
+/// fallback [AppLocalizations] uses for anything it does not serve.
+DeveloperNote developerNoteFor(String locale) =>
+ _developerNotes[locale] ?? _developerNotes['zh_TW']!;
diff --git a/lib/features/more/presentation/pages/more_page.dart b/lib/features/more/presentation/pages/more_page.dart
index 9079fdf4c..3676b8cc9 100644
--- a/lib/features/more/presentation/pages/more_page.dart
+++ b/lib/features/more/presentation/pages/more_page.dart
@@ -4,8 +4,8 @@ import 'package:dpip/app/theme/app_gold.dart';
import 'package:dpip/app/theme/app_radius.dart';
import 'package:dpip/app/theme/app_spacing.dart';
import 'package:dpip/core/error/result.dart';
-import 'package:dpip/core/geo/town_directory.dart';
import 'package:dpip/core/logging/log.dart';
+import 'package:dpip/core/geo/town_directory.dart';
import 'package:dpip/core/meshtastic/mesh_unread.dart';
import 'package:dpip/core/network/endpoint_health.dart';
import 'package:dpip/core/settings/default_map_layer_controller.dart';
@@ -15,6 +15,7 @@ import 'package:dpip/core/settings/region_store.dart';
import 'package:dpip/core/version/app_build.dart';
import 'package:dpip/features/changelog/domain/changelog_repository.dart';
import 'package:dpip/features/changelog/domain/release_note.dart';
+import 'package:dpip/features/more/domain/developer_note.dart';
import 'package:dpip/l10n/gen/app_localizations.dart';
import 'package:dpip/shared/map/default_map_layer_ui.dart';
import 'package:dpip/core/permissions/permission_health.dart';
@@ -37,265 +38,343 @@ class MorePage extends StatelessWidget {
final mapLayer = context.watch().layer;
final eewCwaOnly = context.watch().enabled;
return Scaffold(
- appBar: AppBar(title: Text(l10n.navMore)),
- body: ListView(
- // The shell uses extendBody, so the list runs behind the bottom nav bar;
- // pad the bottom by the obscured height (reported via MediaQuery) so the
- // last rows can scroll clear of it.
- padding: EdgeInsets.only(
- top: AppSpacing.sm,
- bottom: AppSpacing.xl + MediaQuery.paddingOf(context).bottom,
- ),
- children: [
- // The four cards above the menu, one block: version fills the left
- // half of the line, support takes the top half of the right column,
- // and Discord and announcements split the bottom half of it.
- const _HeroCards(),
- SectionHeader(l10n.moreSectionRegion),
- _MoreGroup(
- children: [
- const _SavedRegionsTile(),
- _SaveNote(l10n: l10n),
- ],
+ body: SafeArea(
+ bottom: false,
+ child: ListView(
+ // The shell uses extendBody, so the list runs behind the bottom nav bar;
+ // pad the bottom by the obscured height (reported via MediaQuery) so the
+ // last rows can scroll clear of it.
+ padding: EdgeInsets.only(
+ top: AppSpacing.sm,
+ bottom: AppSpacing.xl + MediaQuery.paddingOf(context).bottom,
),
- SectionHeader(l10n.moreSectionNotify),
- _MoreGroup(
- children: [
- _MoreTile(
- icon: Icons.notifications_outlined,
- title: l10n.notifySettingsMenu,
- onTap: () => context.pushNamed(AppRoutes.notifySettings),
- ),
- // Kept beside the notification settings: when an alert does not
- // arrive, the grant is the first thing to check.
- _MoreTile(
- icon: Icons.verified_user_outlined,
- title: l10n.permissionsTitle,
- // The same dot the More tab carries, on the row it leads to —
- // otherwise the tab says something is wrong and the page the
- // user opens looks no different from every other row.
- alert: context.select(
- (health) => health.needsAttention,
+ children: [
+ // The four cards above the menu, one block: version fills the left
+ // half of the line, support takes the top half of the right column,
+ // and Discord and announcements split the bottom half of it.
+ const _HeroCards(),
+ // Straight under the support callout: the developers' current
+ // word, tracked in Dart rather than ARB because it moves faster
+ // than a release cycle.
+ const _DeveloperNoteCard(),
+ SectionHeader(l10n.moreSectionRegion),
+ _MoreGroup(
+ children: [
+ const _SavedRegionsTile(),
+ _SaveNote(l10n: l10n),
+ ],
+ ),
+ SectionHeader(l10n.moreSectionNotify),
+ _MoreGroup(
+ children: [
+ _MoreTile(
+ icon: Icons.notifications_outlined,
+ title: l10n.notifySettingsMenu,
+ onTap: () => context.pushNamed(AppRoutes.notifySettings),
),
- onTap: () => context.pushNamed(AppRoutes.permissions),
- ),
- // What the system says actually went out — a status page, kept
- // in the notification group because that is where you look when
- // an alert did not arrive.
- _MoreLinkTile(
- icon: Icons.notifications_active_outlined,
- title: l10n.moreNotifyLog,
- host: 'status.exptech.com.tw',
- url: 'https://status.exptech.com.tw/notify',
- ),
- ],
- ),
- SectionHeader(l10n.moreSectionDisplay),
- _MoreGroup(
- children: [
- _MoreTile(
- icon: Icons.translate_outlined,
- title: l10n.languageSettings,
- onTap: () => context.pushNamed(AppRoutes.language),
- ),
- _MoreTile(
- icon: Icons.brightness_6_outlined,
- title: l10n.displaySettings,
- onTap: () => context.pushNamed(AppRoutes.display),
- ),
- _MoreTile(
- icon: mapLayer.icon,
- title: l10n.defaultMapLayerSettings,
- subtitle: mapLayer.label(l10n),
- onTap: () => context.pushNamed(AppRoutes.defaultMapLayer),
- ),
- _MoreTile(
- icon: Icons.filter_alt_outlined,
- title: l10n.eewSourceSettings,
- subtitle: eewCwaOnly
- ? l10n.eewSourceCwaOnly
- : l10n.eewSourceAll,
- onTap: () => context.pushNamed(AppRoutes.eewSource),
- ),
- ],
- ),
- // Its own section rather than a row under 進階: the LoRa mesh is the
- // app's off-grid reception path, not a developer curiosity, and the
- // radio it pairs with is a physical thing the user owns and manages.
- SectionHeader(l10n.moreSectionMesh),
- _MoreGroup(
- children: [
- _MoreTile(
- icon: Icons.router_outlined,
- title: l10n.meshtasticTitle,
- // A message arrived in a conversation the user has not read —
- // the same state as the chat page's unread pills, selected
- // down to one boolean so only this tile rebuilds.
- alert: context.select((u) => u.hasUnread),
- onTap: () => context.pushNamed(AppRoutes.meshtastic),
- ),
- ],
- ),
- SectionHeader(l10n.moreSectionAdvanced),
- _MoreGroup(
- children: [
- // Hidden until ten taps on the Developer page's version row
- // (ExperimentalSettings.unlocked).
- if (context.watch().unlocked)
+ // Kept beside the notification settings: when an alert does not
+ // arrive, the grant is the first thing to check.
_MoreTile(
- icon: Icons.science_outlined,
- title: l10n.experimentalFeatures,
- onTap: () => context.pushNamed(AppRoutes.experimental),
+ icon: Icons.verified_user_outlined,
+ title: l10n.permissionsTitle,
+ // The same dot the More tab carries, on the row it leads to —
+ // otherwise the tab says something is wrong and the page the
+ // user opens looks no different from every other row.
+ alert: context.select(
+ (health) => health.needsAttention,
+ ),
+ onTap: () => context.pushNamed(AppRoutes.permissions),
),
- _MoreTile(
- icon: Icons.history_outlined,
- title: l10n.changelogTitle,
- onTap: () => context.pushNamed(AppRoutes.changelog),
- ),
- _MoreTile(
- icon: Icons.article_outlined,
- title: l10n.appLogs,
- onTap: () => context.pushNamed(AppRoutes.log),
- ),
- _MoreTile(
- icon: Icons.developer_mode_outlined,
- title: l10n.moreDeveloper,
- onTap: () => context.pushNamed(AppRoutes.developer),
- ),
- // Directly under the page it dumps. Everything a report needs
- // is on that page already, and it was still being retyped row by
- // row — this sends the whole thing, plus the log that explains
- // it, and hands back one link.
- const _DumpTile(),
- ],
- ),
- SectionHeader(l10n.moreSectionLinks),
- _MoreGroup(
- children: [
- _MoreLinkTile(
- icon: Icons.crisis_alert_outlined,
- title: l10n.moreCwaEew,
- host: 'eew.exptech.dev',
- url: 'https://eew.exptech.dev/',
- ),
- _MoreLinkTile(
- icon: Icons.sensors_outlined,
- title: l10n.moreTremReport,
- host: 'report.exptech.dev',
- url: 'https://report.exptech.dev/',
- ),
- _MoreLinkTile(
- icon: Icons.smart_display_outlined,
- title: l10n.moreYoutube,
- host: 'youtube.com/@exptechtw',
- url: 'https://www.youtube.com/@exptechtw',
- ),
- _MoreLinkTile(
- icon: Icons.groups_outlined,
- title: l10n.moreGithub,
- host: 'github.com/ExpTechTW',
- url: 'https://github.com/ExpTechTW',
- ),
- _MoreLinkTile(
- icon: Icons.code_outlined,
- title: l10n.moreSourceCode,
- host: 'github.com/ExpTechTW/DPIP',
- url: 'https://github.com/ExpTechTW/DPIP',
- ),
- ],
- ),
- // Both stores shown side by side — DPIP is cross-platform.
- SectionHeader(l10n.moreSectionApp),
- _MoreGroup(
- children: [
- _MoreLinkTile(
- icon: Icons.android,
- title: l10n.moreGooglePlay,
- host: 'play.google.com',
- url: 'https://play.google.com/store/apps/details?id=com.exptech.dpip',
- ),
- _MoreLinkTile(
- icon: Icons.apple,
- title: l10n.moreAppStore,
- host: 'apps.apple.com',
- url: 'https://apps.apple.com/tw/app/dpip/id6468026362',
- ),
- ],
- ),
- // The bleeding-edge builds, one per store, each with its own opt-in.
- SectionHeader(l10n.moreSectionBeta),
- _MoreGroup(
- children: [
- _MoreLinkTile(
- icon: Icons.android,
- title: l10n.moreAndroidBeta,
- host: 'play.google.com',
- url: 'https://play.google.com/apps/testing/com.exptech.dpip',
- ),
- _MoreLinkTile(
- icon: Icons.apple,
- title: l10n.moreTestFlight,
- host: 'testflight.apple.com',
- url: 'https://testflight.apple.com/join/8aPWtOxk',
- ),
- ],
- ),
- // The people who make DPIP run — the same list as the README.
- SectionHeader(l10n.moreSectionPartners),
- Padding(
- padding: const EdgeInsets.fromLTRB(
- AppSpacing.lg,
- 0,
- AppSpacing.lg,
- AppSpacing.sm,
+ // What the system says actually went out — a status page, kept
+ // in the notification group because that is where you look when
+ // an alert did not arrive.
+ _MoreLinkTile(
+ icon: Icons.notifications_active_outlined,
+ title: l10n.moreNotifyLog,
+ host: 'status.exptech.com.tw',
+ url: 'https://status.exptech.com.tw/notify',
+ ),
+ ],
),
- child: Text(
- l10n.morePartnersNote,
- style: Theme.of(context).textTheme.bodySmall?.copyWith(
- color: Theme.of(context).colorScheme.onSurfaceVariant,
- ),
+ SectionHeader(l10n.moreSectionDisplay),
+ _MoreGroup(
+ children: [
+ _MoreTile(
+ icon: Icons.translate_outlined,
+ title: l10n.languageSettings,
+ onTap: () => context.pushNamed(AppRoutes.language),
+ ),
+ _MoreTile(
+ icon: Icons.brightness_6_outlined,
+ title: l10n.displaySettings,
+ onTap: () => context.pushNamed(AppRoutes.display),
+ ),
+ _MoreTile(
+ icon: mapLayer.icon,
+ title: l10n.defaultMapLayerSettings,
+ subtitle: mapLayer.label(l10n),
+ onTap: () => context.pushNamed(AppRoutes.defaultMapLayer),
+ ),
+ _MoreTile(
+ icon: Icons.filter_alt_outlined,
+ title: l10n.eewSourceSettings,
+ subtitle: eewCwaOnly
+ ? l10n.eewSourceCwaOnly
+ : l10n.eewSourceAll,
+ onTap: () => context.pushNamed(AppRoutes.eewSource),
+ ),
+ ],
),
- ),
- _MoreGroup(
- children: [
- _MoreLinkTile(
- icon: Icons.business_outlined,
- title: l10n.morePartnerGeoscience,
- host: 'geoscience.com.tw',
- url: 'https://www.geoscience.com.tw/',
+ // Its own section rather than a row under 進階: the LoRa mesh is the
+ // app's off-grid reception path, not a developer curiosity, and the
+ // radio it pairs with is a physical thing the user owns and manages.
+ SectionHeader(l10n.moreSectionMesh),
+ _MoreGroup(
+ children: [
+ _MoreTile(
+ icon: Icons.router_outlined,
+ title: l10n.meshtasticTitle,
+ // A message arrived in a conversation the user has not read —
+ // the same state as the chat page's unread pills, selected
+ // down to one boolean so only this tile rebuilds.
+ alert: context.select((u) => u.hasUnread),
+ onTap: () => context.pushNamed(AppRoutes.meshtastic),
+ ),
+ ],
+ ),
+ SectionHeader(l10n.moreSectionAdvanced),
+ _MoreGroup(
+ children: [
+ // Hidden until ten taps on the Developer page's version row
+ // (ExperimentalSettings.unlocked).
+ if (context.watch().unlocked)
+ _MoreTile(
+ icon: Icons.science_outlined,
+ title: l10n.experimentalFeatures,
+ onTap: () => context.pushNamed(AppRoutes.experimental),
+ ),
+ _MoreTile(
+ icon: Icons.history_outlined,
+ title: l10n.changelogTitle,
+ onTap: () => context.pushNamed(AppRoutes.changelog),
+ ),
+ _MoreTile(
+ icon: Icons.article_outlined,
+ title: l10n.appLogs,
+ onTap: () => context.pushNamed(AppRoutes.log),
+ ),
+ _MoreTile(
+ icon: Icons.developer_mode_outlined,
+ title: l10n.moreDeveloper,
+ onTap: () => context.pushNamed(AppRoutes.developer),
+ ),
+ // Directly under the page it dumps. Everything a report needs
+ // is on that page already, and it was still being retyped row by
+ // row — this sends the whole thing, plus the log that explains
+ // it, and hands back one link.
+ const _DumpTile(),
+ ],
+ ),
+ SectionHeader(l10n.moreSectionLinks),
+ _MoreGroup(
+ children: [
+ _MoreLinkTile(
+ icon: Icons.crisis_alert_outlined,
+ title: l10n.moreCwaEew,
+ host: 'eew.exptech.dev',
+ url: 'https://eew.exptech.dev/',
+ ),
+ _MoreLinkTile(
+ icon: Icons.sensors_outlined,
+ title: l10n.moreTremReport,
+ host: 'report.exptech.dev',
+ url: 'https://report.exptech.dev/',
+ ),
+ _MoreLinkTile(
+ icon: Icons.smart_display_outlined,
+ title: l10n.moreYoutube,
+ host: 'youtube.com/@exptechtw',
+ url: 'https://www.youtube.com/@exptechtw',
+ ),
+ _MoreLinkTile(
+ icon: Icons.groups_outlined,
+ title: l10n.moreGithub,
+ host: 'github.com/ExpTechTW',
+ url: 'https://github.com/ExpTechTW',
+ ),
+ _MoreLinkTile(
+ icon: Icons.code_outlined,
+ title: l10n.moreSourceCode,
+ host: 'github.com/ExpTechTW/DPIP',
+ url: 'https://github.com/ExpTechTW/DPIP',
+ ),
+ ],
+ ),
+ // Both stores shown side by side — DPIP is cross-platform.
+ SectionHeader(l10n.moreSectionApp),
+ _MoreGroup(
+ children: [
+ _MoreLinkTile(
+ icon: Icons.android,
+ title: l10n.moreGooglePlay,
+ host: 'play.google.com',
+ url: 'https://play.google.com/store/apps/details?id=com.exptech.dpip',
+ ),
+ _MoreLinkTile(
+ icon: Icons.apple,
+ title: l10n.moreAppStore,
+ host: 'apps.apple.com',
+ url: 'https://apps.apple.com/tw/app/dpip/id6468026362',
+ ),
+ ],
+ ),
+ // The bleeding-edge builds, one per store, each with its own opt-in.
+ SectionHeader(l10n.moreSectionBeta),
+ _MoreGroup(
+ children: [
+ _MoreLinkTile(
+ icon: Icons.android,
+ title: l10n.moreAndroidBeta,
+ host: 'play.google.com',
+ url: 'https://play.google.com/apps/testing/com.exptech.dpip',
+ ),
+ _MoreLinkTile(
+ icon: Icons.apple,
+ title: l10n.moreTestFlight,
+ host: 'testflight.apple.com',
+ url: 'https://testflight.apple.com/join/8aPWtOxk',
+ ),
+ ],
+ ),
+ // The people who make DPIP run — the same list as the README.
+ SectionHeader(l10n.moreSectionPartners),
+ Padding(
+ padding: const EdgeInsets.fromLTRB(
+ AppSpacing.lg,
+ 0,
+ AppSpacing.lg,
+ AppSpacing.sm,
),
- _MoreLinkTile(
- icon: Icons.cloud_outlined,
- title: l10n.morePartnerTwds,
- host: 'twds.com.tw',
- url: 'https://www.twds.com.tw/',
+ child: Text(
+ l10n.morePartnersNote,
+ style: Theme.of(context).textTheme.bodySmall?.copyWith(
+ color: Theme.of(context).colorScheme.onSurfaceVariant,
+ ),
),
- ],
+ ),
+ _MoreGroup(
+ children: [
+ _MoreLinkTile(
+ icon: Icons.business_outlined,
+ title: l10n.morePartnerGeoscience,
+ host: 'geoscience.com.tw',
+ url: 'https://www.geoscience.com.tw/',
+ ),
+ _MoreLinkTile(
+ icon: Icons.cloud_outlined,
+ title: l10n.morePartnerTwds,
+ host: 'twds.com.tw',
+ url: 'https://www.twds.com.tw/',
+ ),
+ ],
+ ),
+ SectionHeader(l10n.moreSectionAbout),
+ _MoreGroup(
+ children: [
+ _MoreLinkTile(
+ icon: Icons.gavel_outlined,
+ title: l10n.termsOfService,
+ host: 'exptech.com.tw',
+ url: 'https://exptech.com.tw/tos',
+ ),
+ _MoreTile(
+ icon: Icons.inventory_2_outlined,
+ title: l10n.openSourceLicenses,
+ // Flutter's built-in license viewer — no third-party package.
+ onTap: () => showLicensePage(
+ context: context,
+ applicationName: 'DPIP',
+ ),
+ ),
+ _MoreLinkTile(
+ icon: Icons.help_outline,
+ title: l10n.faq,
+ host: 'exptech.com.tw',
+ url: 'https://exptech.com.tw',
+ ),
+ ],
+ ),
+ const _DataSourceAttributions(),
+ ],
+ ),
+ ),
+ );
+ }
+}
+
+class _DataSourceAttributions extends StatelessWidget {
+ const _DataSourceAttributions();
+
+ @override
+ Widget build(BuildContext context) {
+ final l10n = AppLocalizations.of(context);
+ final theme = Theme.of(context);
+ final color = theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.62);
+ final sources = [
+ l10n.dataSourceTremNet,
+ l10n.dataSourceCwa,
+ l10n.dataSourceJma,
+ l10n.dataSourceNcdr,
+ l10n.dataSourceEcmwf,
+ l10n.dataSourceNoaaGfs,
+ l10n.dataSourceGovernmentOpenData,
+ l10n.dataSourceOpenStreetMap,
+ l10n.dataSourceNasaMoon,
+ ];
+ return Padding(
+ padding: const EdgeInsets.fromLTRB(
+ AppSpacing.lg,
+ AppSpacing.xs,
+ AppSpacing.lg,
+ 0,
+ ),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ l10n.moreDataSources,
+ style: theme.textTheme.labelSmall?.copyWith(
+ color: theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.78),
+ fontWeight: FontWeight.w600,
+ ),
),
- SectionHeader(l10n.moreSectionAbout),
- _MoreGroup(
- children: [
- _MoreLinkTile(
- icon: Icons.gavel_outlined,
- title: l10n.termsOfService,
- host: 'exptech.com.tw',
- url: 'https://exptech.com.tw/tos',
- ),
- _MoreTile(
- icon: Icons.inventory_2_outlined,
- title: l10n.openSourceLicenses,
- // Flutter's built-in license viewer — no third-party package.
- onTap: () =>
- showLicensePage(context: context, applicationName: 'DPIP'),
- ),
- _MoreLinkTile(
- icon: Icons.help_outline,
- title: l10n.faq,
- host: 'exptech.com.tw',
- url: 'https://exptech.com.tw',
+ const SizedBox(height: AppSpacing.xs),
+ for (final source in sources)
+ Padding(
+ padding: const EdgeInsets.only(bottom: 3),
+ child: Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Padding(
+ padding: const EdgeInsets.only(top: 6),
+ child: DecoratedBox(
+ decoration: BoxDecoration(
+ color: color,
+ shape: BoxShape.circle,
+ ),
+ child: const SizedBox.square(dimension: 3),
+ ),
+ ),
+ const SizedBox(width: AppSpacing.xs),
+ Expanded(
+ child: Text(
+ source,
+ style: theme.textTheme.labelSmall?.copyWith(color: color),
+ ),
+ ),
+ ],
),
- ],
- ),
+ ),
],
),
);
@@ -716,6 +795,80 @@ class _HeroCards extends StatelessWidget {
}
}
+/// The developers' current word, right under the support callout.
+///
+/// A quiet flat card, one step below the hero column: it asks nothing and it
+/// is not an entry point, so it carries the same neutral surface as the
+/// announcement card but none of its link affordance. The copy lives in
+/// [developerNoteFor] — Dart, not ARB, because a note about a live incident
+/// is outdated by the time an ARB change reaches a store build.
+class _DeveloperNoteCard extends StatelessWidget {
+ const _DeveloperNoteCard();
+
+ @override
+ Widget build(BuildContext context) {
+ final theme = Theme.of(context);
+ final colors = theme.colorScheme;
+ final note = developerNoteFor(Localizations.localeOf(context).toString());
+ return Padding(
+ padding: const EdgeInsets.fromLTRB(
+ AppSpacing.lg,
+ 0,
+ AppSpacing.lg,
+ AppSpacing.md,
+ ),
+ child: Material(
+ color: colors.surfaceContainerHigh,
+ borderRadius: AppRadius.large,
+ clipBehavior: Clip.antiAlias,
+ child: Padding(
+ padding: const EdgeInsets.all(AppSpacing.md),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ children: [
+ Container(
+ width: 34,
+ height: 34,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ color: colors.surfaceContainerHighest,
+ ),
+ child: Icon(
+ Icons.chat_bubble_outline,
+ color: colors.onSurfaceVariant,
+ size: 19,
+ ),
+ ),
+ const SizedBox(width: AppSpacing.sm),
+ Expanded(
+ child: Text(
+ note.title,
+ style: theme.textTheme.titleSmall?.copyWith(
+ fontWeight: FontWeight.w600,
+ color: colors.onSurface,
+ ),
+ ),
+ ),
+ ],
+ ),
+ const SizedBox(height: AppSpacing.sm),
+ Text(
+ note.body,
+ style: theme.textTheme.bodySmall?.copyWith(
+ color: colors.onSurfaceVariant,
+ height: 1.5,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
+
/// The page's primary call to action.
///
/// DPIP carries no ads, so this is the only thing on the page actually asking
@@ -1054,11 +1207,20 @@ class _VersionCardState extends State<_VersionCard> {
static const Color _stableColor = Color(0xFF2E7D32);
static const Color _snapshotColor = Color(0xFFEF6C00);
- /// The contributors of the release this build answers for, parsed from the
- /// note's body; empty until the fetch resolves (or when it fails — avatars
- /// are decoration, so a failure only hides them).
+ /// The contributors of the release this build answers for. A build that no
+ /// published release names yet (a local/dev build, or a snapshot newer than
+ /// the fetched page) falls back to the newest note's contributors — the
+ /// closest published record — so the card is never bare once any note has
+ /// been fetched. Empty only when the fetch itself fails.
List _contributors = const [];
+ /// Whether the avatar slot shows a skeleton. True from the first frame and
+ /// **stays true when the fetch fails**: a failed request is indistinguishable
+ /// from a slow one to the reader, and collapsing the slot would move the
+ /// badge row and make the card feel broken — so the placeholder persists
+ /// until real data replaces it.
+ bool _loading = true;
+
@override
void initState() {
super.initState();
@@ -1069,10 +1231,18 @@ class _VersionCardState extends State<_VersionCard> {
final result = await context.read().releases(page: 1);
if (!mounted) return;
setState(() {
- _contributors = switch (result) {
- Ok(:final value) => _contributorsFor(value, AppBuild.label),
- Err() => const [],
- };
+ // Failure keeps the skeleton: `_loading` stays true, and the strip
+ // below renders the placeholder instead of collapsing.
+ switch (result) {
+ case Ok(:final value):
+ _loading = false;
+ _contributors = _contributorsFor(value, AppBuild.label);
+ case Err():
+ Log.debug(
+ 'version card contributors: fetch failed: '
+ '${result.failureOrNull}',
+ );
+ }
});
}
@@ -1083,7 +1253,15 @@ class _VersionCardState extends State<_VersionCard> {
for (final note in notes) {
if (_isCurrent(note, label)) return contributorsFromBody(note.body);
}
- return const [];
+ if (notes.isEmpty) return const [];
+ // No released note names this build (a dev/local label, or a snapshot
+ // newer than this page) — fall back to the newest note's record. Newest
+ // by publish time, not list position: a page's order is the API's to
+ // promise, and the card must not depend on it.
+ final newest = notes.reduce(
+ (a, b) => a.publishedAt.isAfter(b.publishedAt) ? a : b,
+ );
+ return contributorsFromBody(newest.body);
}
/// Whether a release answers for the running [label]. Mirrors the version
@@ -1134,7 +1312,7 @@ class _VersionCardState extends State<_VersionCard> {
clipBehavior: Clip.antiAlias,
child: InkWell(
borderRadius: AppRadius.large,
- onTap: () => context.pushNamed(AppRoutes.releaseHighlights),
+ onTap: () => context.pushNamed(AppRoutes.versionNotes),
child: Padding(
padding: const EdgeInsets.all(AppSpacing.md),
child: Column(
@@ -1218,6 +1396,16 @@ class _VersionCardState extends State<_VersionCard> {
),
),
const SizedBox(height: AppSpacing.sm),
+ if (_loading || _contributors.isNotEmpty) ...[
+ // The strip sits between the fine-print version and the
+ // type badge — a band of faces under the number. While the
+ // fetch is in flight the slot is reserved by a skeleton, so
+ // the badge row below never jumps when the avatars land.
+ _loading
+ ? const _AvatarSkeleton()
+ : _ContributorStack(contributors: _contributors),
+ const SizedBox(height: AppSpacing.sm),
+ ],
// Same treatment as the changelog's type chip: tinted wash,
// hairline of the same hue, coloured label — not a solid fill,
// which is the one marker the changelog never uses. The badge
@@ -1265,19 +1453,6 @@ class _VersionCardState extends State<_VersionCard> {
],
],
),
- if (_contributors.isNotEmpty) ...[
- // Try to keep a silhouette of the strip against the card:
- // enough of a gap to read as a separate zone, then a hairline
- // that separates the avatars from the build stamp above.
- const SizedBox(height: AppSpacing.sm),
- Divider(
- height: 1,
- thickness: 1,
- color: colors.outlineVariant.withValues(alpha: 0.5),
- ),
- const SizedBox(height: AppSpacing.sm),
- _ContributorStack(contributors: _contributors),
- ],
],
),
),
@@ -1286,6 +1461,41 @@ class _VersionCardState extends State<_VersionCard> {
}
}
+/// The skeleton that reserves the contributor slot while the changelog fetch
+/// is in flight — three dim circles at the stack's natural footprint, so the
+/// card keeps its height from the first frame and the swap to real avatars
+/// moves nothing below it.
+class _AvatarSkeleton extends StatelessWidget {
+ const _AvatarSkeleton();
+
+ @override
+ Widget build(BuildContext context) {
+ final colors = Theme.of(context).colorScheme;
+ final fill = colors.surfaceContainerHighest.withValues(alpha: 0.45);
+ return SizedBox(
+ width: 3 * _ContributorStack._extra + _ContributorStack._size,
+ height: _ContributorStack._size,
+ child: Stack(
+ children: [
+ for (var i = 0; i < 3; i++)
+ Positioned(
+ left: i * _ContributorStack._extra,
+ child: Container(
+ width: _ContributorStack._size - 4,
+ height: _ContributorStack._size - 4,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ color: fill,
+ border: Border.all(color: colors.surfaceContainer, width: 2),
+ ),
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
+
/// A width-adaptive stack of contributor avatars for the version card.
///
/// Allocates as many avatars as the card's width offers — as the card is
@@ -1301,7 +1511,11 @@ class _ContributorStack extends StatelessWidget {
static const double _overlap = 14;
/// Avatar circle diameter, including the border.
- static const double _size = 24;
+ static const double _size = 30;
+
+ /// Horizontal advance per avatar — size minus the overlap, so the far edge
+ /// of each circle sits exactly under the previous one's border.
+ static const double _extra = _size - _overlap;
@override
Widget build(BuildContext context) {
@@ -1313,10 +1527,9 @@ class _ContributorStack extends StatelessWidget {
var shown = 1;
// First avatar takes _size; each further one adds (size - overlap).
var used = _size;
- final extra = _size - _overlap;
while (shown < contributors.length &&
- used + extra + chipWidth <= constraints.maxWidth) {
- used += extra;
+ used + _extra + chipWidth <= constraints.maxWidth) {
+ used += _extra;
shown++;
}
final hidden = contributors.length - shown;
@@ -1328,7 +1541,7 @@ class _ContributorStack extends StatelessWidget {
children: [
for (var i = 0; i < shown; i++)
Positioned(
- left: i * extra,
+ left: i * _extra,
child: _VersionAvatar(contributor: contributors[i]),
),
if (hidden > 0)
@@ -1406,7 +1619,7 @@ class _VersionAvatarState extends State<_VersionAvatar> {
? '?'
: widget.contributor.login[0].toUpperCase(),
style: Theme.of(context).textTheme.labelSmall?.copyWith(
- fontSize: 9,
+ fontSize: 11,
color: colors.onSurfaceVariant,
fontWeight: FontWeight.w700,
),
@@ -1440,7 +1653,7 @@ class _MoreChip extends StatelessWidget {
child: Text(
'+$count',
style: Theme.of(context).textTheme.labelSmall?.copyWith(
- fontSize: 8,
+ fontSize: 10,
color: colors.onSurfaceVariant,
fontWeight: FontWeight.w700,
),
diff --git a/lib/features/onboarding/presentation/widgets/onboarding_scaffold.dart b/lib/features/onboarding/presentation/widgets/onboarding_scaffold.dart
index 8fa919dcc..f04987ce6 100644
--- a/lib/features/onboarding/presentation/widgets/onboarding_scaffold.dart
+++ b/lib/features/onboarding/presentation/widgets/onboarding_scaffold.dart
@@ -28,13 +28,14 @@ class OnboardingScaffold extends StatefulWidget {
class _OnboardingScaffoldState extends State {
final ScrollController _controller = ScrollController();
bool _atEnd = false;
+ bool _checkScheduled = false;
@override
void initState() {
super.initState();
_controller.addListener(_check);
// Content that fits without scrolling counts as already "at end".
- WidgetsBinding.instance.addPostFrameCallback((_) => _check());
+ _scheduleCheck();
}
@override
@@ -45,7 +46,16 @@ class _OnboardingScaffoldState extends State {
// re-evaluate "at end" after the new content lays out; otherwise a
// scroll-gated step (the terms) would stay locked with an un-scrollable
// "scroll to continue" hint.
- WidgetsBinding.instance.addPostFrameCallback((_) => _check());
+ _scheduleCheck();
+ }
+
+ void _scheduleCheck() {
+ if (_checkScheduled) return;
+ _checkScheduled = true;
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ _checkScheduled = false;
+ if (mounted) _check();
+ });
}
void _check() {
@@ -70,12 +80,24 @@ class _OnboardingScaffoldState extends State {
return Column(
children: [
Expanded(
- child: Scrollbar(
- controller: _controller,
- child: SingleChildScrollView(
+ // A ScrollController reports pixel motion, not changes to its
+ // viewport or content dimensions. Android may settle display DPI or
+ // system insets after the first layout; if that makes the whole body
+ // fit, there is then no scroll gesture capable of re-running _check.
+ // Listen to metrics as well so an unscrollable page cannot stay
+ // locked behind "scroll down to continue".
+ child: NotificationListener(
+ onNotification: (_) {
+ _scheduleCheck();
+ return false;
+ },
+ child: Scrollbar(
controller: _controller,
- padding: const EdgeInsets.all(AppSpacing.lg),
- child: widget.child,
+ child: SingleChildScrollView(
+ controller: _controller,
+ padding: const EdgeInsets.all(AppSpacing.lg),
+ child: widget.child,
+ ),
),
),
),
diff --git a/lib/features/release_highlights/presentation/pages/release_highlights_page.dart b/lib/features/release_highlights/presentation/pages/release_highlights_page.dart
index a52b3cab8..3790932f7 100644
--- a/lib/features/release_highlights/presentation/pages/release_highlights_page.dart
+++ b/lib/features/release_highlights/presentation/pages/release_highlights_page.dart
@@ -3,15 +3,15 @@
library;
import 'package:dpip/app/theme/app_spacing.dart';
+import 'package:dpip/core/version/app_build.dart';
import 'package:dpip/features/release_highlights/domain/release_highlight.dart';
import 'package:dpip/features/release_highlights/presentation/widgets/highlight_card.dart';
import 'package:dpip/l10n/gen/app_localizations.dart';
-import 'package:dpip/shared/navigation/app_routes.dart';
import 'package:flutter/material.dart';
-import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
-/// The page behind the version card's chevron.
+/// The page behind the version card's chevron — the train's key highlights
+/// and technical notes.
class ReleaseHighlightsPage extends StatelessWidget {
const ReleaseHighlightsPage({super.key});
@@ -22,14 +22,7 @@ class ReleaseHighlightsPage extends StatelessWidget {
length: 2,
child: Scaffold(
appBar: AppBar(
- title: Text(l10n.releaseHighlightsTitle),
- actions: [
- IconButton(
- icon: const Icon(Icons.article_outlined),
- tooltip: l10n.releaseHighlightsSeeNotes,
- onPressed: () => context.pushNamed(AppRoutes.versionNotes),
- ),
- ],
+ title: Text(l10n.releaseHighlightsTitle(AppBuild.train)),
bottom: TabBar(
tabs: [
Tab(text: l10n.releaseHighlightsTabNormal),
diff --git a/lib/features/settings/presentation/pages/developer_page.dart b/lib/features/settings/presentation/pages/developer_page.dart
index 1cf23a5f9..63506d7d2 100644
--- a/lib/features/settings/presentation/pages/developer_page.dart
+++ b/lib/features/settings/presentation/pages/developer_page.dart
@@ -228,7 +228,7 @@ class _DeveloperPageState extends State {
String? _diagnosticsText() {
final sections = _sections;
if (sections == null) return null;
- return diagnosticsText(sections, redacted: diagnosticsRedactedLabels);
+ return diagnosticsText(sections, redacted: diagnosticsSensitiveLabels);
}
@override
diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb
index 011efa859..f37be1347 100644
--- a/lib/l10n/app_en.arb
+++ b/lib/l10n/app_en.arb
@@ -2652,8 +2652,9 @@
"moreAnnouncements": "Announcements",
"moreTagline": "Disaster Prevention Information Platform",
"moreVersionStable": "Release",
- "moreVersionNotes": "This version",
- "releaseHighlightsTitle": "What changed in this release",
+ "moreVersionNotes": "This update",
+ "moreVersionNotesHighlightsSubtitle": "What changed in this release",
+ "releaseHighlightsTitle": "{train} key highlights",
"releaseHighlightsTabNormal": "For users",
"releaseHighlightsTabAdvanced": "Deep dive",
"releaseHighlightsEmpty": "Nothing here yet.",
@@ -2830,6 +2831,54 @@
"@meshtasticChannels": {
"description": "Section: the radio's channel table"
},
+ "mapOsmOverlay": "Detailed map",
+ "mapOsmOverlayHint": "Show more complete roads, buildings, and place labels",
+ "mapOsmDetails": "Detailed map layers",
+ "moreDataSources": "Data sources",
+ "@moreDataSources": {
+ "description": "Heading above the subtle source-attribution list at the bottom of About"
+ },
+ "dataSourceTremNet": "探索智慧科技有限公司 — TREM-Net",
+ "dataSourceCwa": "交通部中央氣象署 (CWA)",
+ "dataSourceJma": "気象庁 (JMA)",
+ "dataSourceNcdr": "國家災害防救科技中心 (NCDR)",
+ "dataSourceEcmwf": "European Centre for Medium-Range Weather Forecasts (ECMWF)",
+ "dataSourceNoaaGfs": "National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)",
+ "dataSourceGovernmentOpenData": "政府資料開放平臺",
+ "dataSourceOpenStreetMap": "© OpenStreetMap contributors",
+ "dataSourceNasaMoon": "National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)",
+ "mapOsmDetailsHint": "{enabled} of {total} layers enabled",
+ "@mapOsmDetailsHint": {
+ "description": "How many of the OSM layers are enabled",
+ "placeholders": {
+ "enabled": {
+ "type": "int"
+ },
+ "total": {
+ "type": "int"
+ }
+ }
+ },
+ "mapOsmSurface": "Surface",
+ "mapOsmParks": "Parks",
+ "mapOsmLandUse": "Land use",
+ "mapOsmAirportAreas": "Airport areas",
+ "mapOsmWater": "Water",
+ "mapOsmRivers": "Rivers",
+ "mapOsmBoundaries": "Boundaries",
+ "mapOsmBuildings": "Buildings",
+ "mapOsmRoads": "Roads",
+ "mapOsmRoadNames": "Road names",
+ "mapOsmWaterNames": "Water names",
+ "mapOsmPeaks": "Peaks",
+ "mapOsmAirportNames": "Airport names",
+ "mapOsmPlaceNames": "Place names",
+ "mapOsmPoi": "Points of interest",
+ "mapOsmHouseNumbers": "House numbers",
+ "mapOsmRestoreAll": "Restore all",
+ "mapOsmSectionNatural": "Natural features",
+ "mapOsmSectionRoadsAndBuildings": "Roads & buildings",
+ "mapOsmSectionLabelsAndPlaces": "Labels & places",
"mapTownLabels": "Township names",
"@typhoonOverlayWarningTooltip": {
"description": "Tooltip for the warning-areas overlay toggle"
@@ -3554,6 +3603,30 @@
"description": "Button that opens the system settings page"
},
"permissionSettingsMessage": "“{what}” was declined, and the system will not ask again. Turn it on in Settings.",
+ "permissionGuideNotification": "Open System Settings to allow notifications.",
+ "permissionGuideForegroundLocation": "Open System Settings to allow precise location.",
+ "permissionGuideBackgroundLocation": "In “{option}”, choose “Allow all the time”.",
+ "@permissionGuideBackgroundLocation": {
+ "description": "Instruction for background location",
+ "placeholders": {
+ "option": {}
+ }
+ },
+ "permissionGuideBackgroundExecution": "Allow background execution in System Settings so notifications are not paused.",
+ "permissionGuideUnusedPause": "If the app is marked “unused”, choose “Allow” in System Settings.",
+ "permissionGuideUnusedFreeSpace": "If the app was paused for storage, clear cache and reopen it.",
+ "permissionGuideUnusedRevoke": "If the app's permissions were revoked, grant them again in System Settings.",
+ "permissionGuideUnusedPlayProtect": "If Play Protect paused the app, check its status in Google Play.",
+ "permissionGuideVendorPower": "In “{vendor}” power-saving settings, set this app to “Unrestricted”.",
+ "@permissionGuideVendorPower": {
+ "description": "Instruction for vendor power saving",
+ "placeholders": {
+ "vendor": {}
+ }
+ },
+ "permissionStillRequired": "Still needs attention. Check the highlighted option in Settings.",
+ "permissionVerifyManually": "Please verify this permission is enabled in System Settings.",
+ "permissionBackgroundLocationOption": "“Allow all the time”",
"@permissionSettingsMessage": {
"description": "Explains that the system will not ask again for this permission",
"placeholders": {
@@ -3752,6 +3825,18 @@
"@moreDumpDiagnosticsHint": {
"description": "Subtitle of the debug-dump row"
},
+ "dumpIncludeSensitive": "Include precise location",
+ "@dumpIncludeSensitive": {
+ "description": "Unchecked-by-default consent for private diagnostics"
+ },
+ "dumpIncludeSensitiveHint": "Includes coordinates from logs and background location; otherwise they are replaced with null",
+ "@dumpIncludeSensitiveHint": {
+ "description": "Explains which diagnostics require explicit consent"
+ },
+ "dumpUpload": "Upload",
+ "@dumpUpload": {
+ "description": "Button that confirms a diagnostics upload"
+ },
"dumpUploaded": "Uploaded",
"@dumpUploaded": {
"description": "Title of the dialog shown after a debug dump uploads"
diff --git a/lib/l10n/app_fil.arb b/lib/l10n/app_fil.arb
index 19b97948e..1674f8ad3 100644
--- a/lib/l10n/app_fil.arb
+++ b/lib/l10n/app_fil.arb
@@ -16,38 +16,38 @@
"description": "LoRa region"
},
"mapLayerSatelliteB03": "Himawari Red (B03)",
- "reportFilterIntensity": "Intensity",
+ "reportFilterIntensity": "Lakas",
"mapLayerLightning": "Kidlat",
"restroomTypeMale": "Palikuran ng lalaki",
- "meshtasticLastReceived": "Last received",
+ "meshtasticLastReceived": "Huling natanggap",
"reportDetailSortByCounty": "Ayusin ayon sa lalawigan",
"@moonDays": {
"description": "Day unit for the moon age"
},
"homeRainTrendScattered": "Posibleng mahinang ulan",
- "meshtasticUptime": "Uptime",
+ "meshtasticUptime": "Oras ng pagtakbo",
"weatherRankingTempExtremes": "Mga sukdulan ng temperatura",
"themeLight": "Maliwanag",
"mapTerrainReliefHint": "Ipakita ang anino ng terrain sa base map",
- "meshtasticEmptyMessage": "(empty message)",
+ "meshtasticEmptyMessage": "(walang laman na mensahe)",
"moreSectionRegion": "Rehiyon",
"mapLayerSatellite": "Himawari Infrared (B13)",
"@meshtasticTapNode": {
"description": "Resting state of the map node sheet"
},
"aedHoursSaturday": "Oras sa Sabado",
- "moonPhaseNew": "New moon",
+ "moonPhaseNew": "Bagong buwan",
"notifySectionEew": "Maagang babala sa lindol",
"mapResetNorth": "Bumalik sa hilaga",
"rainInterval2d": "2 araw",
"mapTownLabelsHint": "Ipakita ang mga pangalan ng bayan kapag naka-zoom",
- "commonCancel": "Cancel",
+ "commonCancel": "Kanselahin",
"notifyOptTsunamiWarning": "Mga babala sa tsunami lamang",
"mapLayerSatelliteBtdFog": "Himawari Night Fog",
"@meshtasticSelectDevice": {
"description": "Device picker sheet title"
},
- "moreSectionAdvanced": "Advanced",
+ "moreSectionAdvanced": "Mas advanced",
"moreSectionMesh": "Mesh network",
"@meshtasticLastHeard": {
"description": "When a node last transmitted"
@@ -59,7 +59,7 @@
"notifySettingsMenu": "Mga setting ng notipikasyon",
"mapAppDefault": "{app} (default)",
"trendRange24h": "24 oras",
- "mapLayerStyleJmaTooltip": "Grayscale base, tinted below −40 °C to highlight cloud-top height",
+ "mapLayerStyleJmaTooltip": "Grayscale na base, may kulay sa ibaba ng −40 °C para i-highlight ang taas ng ulap",
"mapLayerRain": "Ulan",
"mapLayerQpesums": "Pagtaya ng ulan sa susunod na 1 oras",
"@weatherModeSnow": {
@@ -82,16 +82,16 @@
"changelogShowSnapshots": "Ipakita ang snapshot",
"changelogTitle": "Changelog",
"reportFilterOrderDesc": "Pababa",
- "meshtasticExcludeMqttSubtitle": "Nodes bridged over the internet, not heard by radio",
+ "meshtasticExcludeMqttSubtitle": "Mga node na konektado sa internet, hindi naririnig sa radyo",
"reportFilterIntensityInfoTitle": "Bagong at lumang intensity scale",
"mapLayerTyphoon": "Bagyo",
"radarOverlayMenuTooltip": "Mga opsyon sa layer ng radar",
"@meshtasticChannelUse": {
"description": "Share of airtime seen busy"
},
- "meshtasticNodes": "Nodes",
- "meshtasticSend": "Send",
- "typhoonOverlayStormL7Tooltip": "Level-7 wind field + average circle (purple)",
+ "meshtasticNodes": "Mga node",
+ "meshtasticSend": "Ipadala",
+ "typhoonOverlayStormL7Tooltip": "Larangan ng hangin sa antas 7 + average circle (lila)",
"aedType": "Uri",
"termsOfService": "Mga Tuntunin ng Serbisyo",
"typhoonLegendCircle25": "Storm circle (L10)",
@@ -115,7 +115,7 @@
"description": "Map layer name: mesh nodes"
},
"reportFilterDateEndNote": "End day: through 24:00(Taipei)",
- "meshtasticSilent": "Silent",
+ "meshtasticSilent": "Tahimik",
"reportFilterSortMagnitude": "Magnitude",
"mapLayerCategoryEarthquake": "Lindol",
"mapLayerSatelliteB12": "Himawari Ozone (B12)",
@@ -144,12 +144,12 @@
"@radarCountyOutlineHint": {
"description": "Hint under the county-border toggle in the radar overlay menu."
},
- "meshtasticLayerOptions": "Node options",
+ "meshtasticLayerOptions": "Mga opsyon sa node",
"onboardingAgreeContinue": "Sumang-ayon at magpatuloy",
"meshtasticNodeId": "Node ID",
"commonRetry": "Subukan Muli",
"reportDetailNumbered": "Blg. {number} Makabuluhang Naramdamang Lindol",
- "typhoonOverlayStormBandSubtitle": "With average circle",
+ "typhoonOverlayStormBandSubtitle": "May average circle",
"disasterMapOverlayRestroomTooltip": "Ipakita ang mga pampublikong palikuran",
"weatherRankingTitle": "Mga ranggo ng obserbasyon",
"homeRainTrendHeavySustained": "Tuloy-tuloy na malakas na ulan sa susunod na oras",
@@ -161,23 +161,23 @@
"@meshtasticSilent": {
"description": "Legend: node known but not heard recently"
},
- "meshtasticChannelWorking": "Setting up the DPIP channel…",
- "meshtasticRegionSwitch": "Switch to TW",
+ "meshtasticChannelWorking": "Ini-set up ang DPIP channel…",
+ "meshtasticRegionSwitch": "Lumipat sa TW",
"@meshtasticLastReceived": {
"description": "Age of the last received packet"
},
- "meshtasticTraffic": "Traffic",
+ "meshtasticTraffic": "Trapiko",
"@meshtasticDpipChannel": {
"description": "Which channel DPIP payloads use"
},
- "mapLayerStyleBdTooltip": "Dvorak BD curve — the stepped grayscale for tropical-cyclone intensity analysis",
- "disasterMapOverlayAedTooltip": "Show AED locations",
+ "mapLayerStyleBdTooltip": "Dvorak BD curve — ang stepped grayscale para sa pagsusuri ng lakas ng bagyo",
+ "disasterMapOverlayAedTooltip": "Ipakita ang mga lokasyon ng AED",
"@moonTitle": {
"description": "Moon page title"
},
"mapLayerHumidity": "Halumigmig",
- "mapLayerSatelliteTransparentNight": "Night = transparent, the basemap shows",
- "meshtasticScanning": "Scanning…",
+ "mapLayerSatelliteTransparentNight": "Gabing transparent, makikita ang basemap",
+ "meshtasticScanning": "Nag-scan…",
"@meshtasticDevice": {
"description": "Section: device identity"
},
@@ -203,7 +203,7 @@
"meshtasticTitle": "Meshtastic",
"navMore": "Higit Pa",
"meshtasticDpipChannel": "DPIP channel",
- "disasterMapOverlaySectionLayers": "Layers",
+ "disasterMapOverlaySectionLayers": "Mga layer",
"@moonPhaseWaningCrescent": {
"description": "Phase: waning crescent"
},
@@ -215,15 +215,15 @@
"description": "Label for the weatherModeCloudy option in the experimental backdrop settings."
},
"typhoonLabelNe": "NE",
- "meshtasticCopied": "Message copied",
+ "meshtasticCopied": "Nakopya ang mensahe",
"reportListEmpty": "Walang ulat ng lindol",
"reportListEnd": "Dulo ng listahan",
"mapLayerSatelliteTruecolor": "Himawari True Color",
- "typhoonOverlaySectionExtra": "Overlays",
+ "typhoonOverlaySectionExtra": "Mga overlay",
"eewSWave": "S wave",
- "meshtasticBusyTitle": "Another app is using this radio",
+ "meshtasticBusyTitle": "May ibang app na gumagamit ng radyong ito",
"restroomCategoryCultural": "Pook na pangkultura",
- "typhoonLabelWind": "Max. sustained wind near centre",
+ "typhoonLabelWind": "Max. sustained wind malapit sa gitna",
"radarGlobalOutlineHint": "Panlabas na balangkas ng bawat bansa",
"notifyEvacuation": "Impormasyon sa sakuna",
"typhoonLegendCircle15": "Gale circle (L7)",
@@ -233,11 +233,11 @@
"@meshtasticRadioSettings": {
"description": "Section: LoRa settings"
},
- "dataSectionAstronomy": "Astronomy",
+ "dataSectionAstronomy": "Astronomiya",
"homeRainTrendLightSustained": "Tuloy-tuloy na mahinang ulan sa susunod na oras",
"commonError": "May Nangyaring Mali",
- "moonPhaseWaningCrescent": "Waning crescent",
- "meshtasticPower": "Power",
+ "moonPhaseWaningCrescent": "Lumiit na gasuklay",
+ "meshtasticPower": "Kuryente",
"@meshtasticChannelWorking": {
"description": "Creating/verifying the DPIP channel"
},
@@ -245,7 +245,7 @@
"reportFilterRange": "{start} – {end}",
"reportDetailOpenReport": "Pahina ng Ulat",
"trendRange7d": "7 araw",
- "typhoonWarningAreas": "Areas: {areas}",
+ "typhoonWarningAreas": "Mga lugar: {areas}",
"rainIntervalSection": "Window ng oras",
"notifyTitle": "Mga Notipikasyon",
"meshtasticTxPower": "TX power",
@@ -255,7 +255,7 @@
"restroomCategoryLabel": "Kategorya",
"sponsorRestoring": "Ibinabalik ang mga pagbili…",
"sponsorIntro": "Nakatuon ang DPIP sa pagbibigay ng real-time na impormasyon sa pag-iwas sa sakuna, nang walang ad o iba pang modelo ng kita. Tumutulong ang inyong suporta na mapanatili ang mga server at magpatuloy sa pagbuo.",
- "typhoonLabelStormAvg": "Avg. radius of Beaufort 10 winds",
+ "typhoonLabelStormAvg": "Avg. radius ng Beaufort 10 na hangin",
"@meshtasticHardware": {
"description": "Board model"
},
@@ -274,8 +274,8 @@
"rainInterval6h": "6 oras",
"homeRainTrendMinute": "{minute} min",
"restroomTypeUnspecified": "Hindi natukoy",
- "typhoonOverlayProbabilityHint": "Hides the forecast cone",
- "mapLayerSatelliteGlobalOutline": "Country border",
+ "typhoonOverlayProbabilityHint": "Itinatago ang forecast cone",
+ "mapLayerSatelliteGlobalOutline": "Border ng bansa",
"mapNavTemperature": "Temperatura",
"typhoonLegendForecastPoint": "Punto ng forecast",
"@meshtasticBattery": {
@@ -289,16 +289,16 @@
"rainInterval3d": "3 araw",
"defaultMapLayerSubtitle": "Bubukas ang tab ng Mapa sa layer na ito. Susunod ang icon at label ng bottom navigation.",
"aedDescription": "Tala",
- "typhoonOverlayWeatherRadarTooltip": "Radar echo closest to the typhoon bulletin time",
+ "typhoonOverlayWeatherRadarTooltip": "Radar echo na pinakamalapit sa oras ng bulletin ng bagyo",
"onboardingPermLocationDesc": "Itutok ang mga alerto sa kinaroroonan mo.",
"mapLayerSatelliteB16": "Himawari CO₂ (B16)",
"@meshtasticClearMessages": {
"description": "Menu action clearing the message log"
},
"homeActiveEventsEmpty": "Walang aktibong event",
- "typhoonLabelPosition": "Centre location",
+ "typhoonLabelPosition": "Lokasyon ng gitna",
"weatherRankingBy": "Ayon sa",
- "typhoonIntensityMild": "Mild typhoon",
+ "typhoonIntensityMild": "Mahinang bagyo",
"windForecastGlobalOutlineHint": "Panlabas na balangkas ng bawat bansa",
"rainInterval1h": "1 oras",
"eewLocalIntensity": "Tantiya sa lokasyon",
@@ -308,22 +308,22 @@
},
"restroomCategoryReligious": "Relihiyosong lugar",
"meshtasticRole": "Role",
- "mapLayerSatelliteCloudCloudy": "Cloudy",
- "skyTimeSunrise": "Pagsikat ng araw",
+ "mapLayerSatelliteCloudCloudy": "Maulap",
+ "skyTimeSunrise": "Paosmkat ng araw",
"@mapLayerMeshtasticSubtitle": {
"description": "Map layer switcher subtitle"
},
"meshtasticJumpToLatest": "Pumunta sa pinakabago",
- "meshtasticNoMessages": "No messages yet",
+ "meshtasticNoMessages": "Wala pang mensahe",
"onboardingPermNotifyDesc": "Ihatid ang mga alerto sa lindol, panahon, at sakuna sa sandaling maganap ang mga ito.",
"radarTownOutline": "Mga hangganan ng bayan",
- "mapLayerStyleSection": "Colour style",
+ "mapLayerStyleSection": "Estilo ng kulay",
"@moonPhaseNew": {
"description": "Phase: new moon"
},
- "disasterMapOverlayMenuTooltip": "Disaster map layers",
+ "disasterMapOverlayMenuTooltip": "Mga layer ng disaster map",
"moreGooglePlay": "Google Play",
- "meshtasticOnline": "Heard recently",
+ "meshtasticOnline": "Kamakailang narinig",
"@meshtasticSendHint": {
"description": "Message input hint"
},
@@ -331,7 +331,7 @@
"typhoonForecastLead": "Forecast +{hours} h",
"@mapAppOpenFailed": {},
"changelogTypeStable": "Stable",
- "mapLayerSatelliteTransparentClear": "Clear sky = transparent, the basemap shows",
+ "mapLayerSatelliteTransparentClear": "Maaliwalas = transparent, makikita ang basemap",
"@skyTimeAuto": {
"description": "Label for the skyTimeAuto option in the experimental backdrop settings."
},
@@ -347,14 +347,14 @@
"notifySectionOther": "Iba pa",
"weatherRankingMeta": "Oras ng datos: {time}\n{count} istasyon",
"onboardingTermsAgree": "Nabasa ko na at sumasang-ayon ako sa Mga Tuntunin ng Serbisyo",
- "mapLayerSatelliteTransparentNoVegetation": "Below 0.1 = transparent (no vegetation)",
+ "mapLayerSatelliteTransparentNoVegetation": "Sa ibaba ng 0.1 = transparent (walang vegetation)",
"notifyOptLocalIntensity4": "Lokal na intensidad 4 pataas",
"eewArrived": "Dumating",
- "meshtasticNoDevices": "No Meshtastic devices found",
+ "meshtasticNoDevices": "Walang nahanap na Meshtastic device",
"mapLayerCategoryLife": "Pang-araw-araw na buhay",
- "reportFilterSortIntensity": "Intensity",
- "meshtasticStateDisconnected": "Disconnected",
- "typhoonIntensityIntense": "Intense typhoon",
+ "reportFilterSortIntensity": "Lakas",
+ "meshtasticStateDisconnected": "Naka-disconnect",
+ "typhoonIntensityIntense": "Malakas na bagyo",
"@meshtasticSend": {
"description": "Send message button"
},
@@ -366,10 +366,10 @@
"description": "The radio's short name"
},
"dpmYes": "Oo",
- "meshtasticNoHistory": "Not enough history yet",
+ "meshtasticNoHistory": "Kulang pa sa history",
"reportDetailLocalIntensityUnavailable": "Walang datos ng intensity",
"mapLayerWindForecastGfs": "GFS",
- "reportFilterDepth": "Depth",
+ "reportFilterDepth": "Lalim",
"@meshtasticNoHistory": {
"description": "Chart placeholder before two samples exist"
},
@@ -390,8 +390,8 @@
},
"reportFilterReset": "I-reset",
"mapLayerSatelliteMndwi": "Himawari MNDWI",
- "typhoonOverlaySectionStorm": "Storm wind",
- "moonPhaseFull": "Full moon",
+ "typhoonOverlaySectionStorm": "Hanging bagyo",
+ "moonPhaseFull": "Kabilugan ng buwan",
"@meshtasticEmptyMessage": {
"description": "Placeholder for a text packet with no body"
},
@@ -399,24 +399,24 @@
"@radarGlobalOutlineHint": {
"description": "Hint under the national-border toggle in the radar overlay menu."
},
- "moonPhaseWaningGibbous": "Waning gibbous",
+ "moonPhaseWaningGibbous": "Humihinang bilog",
"reportFilterIntensityInfoModernTitle": "Bago (mula 2020)",
"@mapAppGoogleMaps": {},
- "typhoonDataTime": "Data time\n{time}",
+ "typhoonDataTime": "Oras ng datos",
"restroomTypeAccessible": "Palikurang may accessibility",
"moreSectionAbout": "Tungkol",
- "meshtasticSelectDevice": "Select a radio",
+ "meshtasticSelectDevice": "Pumili ng radyo",
"onboardingIntroBody": "Ang DPIP ang iyong kasama sa pag-iwas sa sakuna. Pinagsasama-sama nito ang mga maagang babala sa lindol, ulat ng lindol, panahon, at impormasyon sa panganib, at inaalertuhan ka sa sandaling mahalaga ito.\n\n• Mga lindol: mga maagang babala, ulat ng intensidad, at detalyadong ulat\n• Panahon: real-time na mensahe ng kulog at kidlat at mga advisory sa panahon\n• Impormasyon sa tsunami at sakuna\n\nSusunod, hihilingin naming basahin mo ang Mga Tuntunin ng Serbisyo at magbigay ng ilang pahintulot para maprotektahan ka ng DPIP nang real time.",
"shelterCapacityLabel": "Kapasidad",
"reportDetailImage": "Larawan ng Ulat",
- "meshtasticStateConfiguring": "Configuring…",
+ "meshtasticStateConfiguring": "Kino-configure…",
"@moonPhaseLastQuarter": {
"description": "Phase: last quarter"
},
- "typhoonLabelGaleAvg": "Avg. radius of Beaufort 7 winds",
+ "typhoonLabelGaleAvg": "Avg. radius ng Beaufort 7 na hangin",
"onboardingPermNotify": "Mga Notipikasyon",
- "meshtasticClearMessages": "Clear messages",
- "meshtasticNotifyMessages": "Notify on new messages",
+ "meshtasticClearMessages": "I-clear ang mga mensahe",
+ "meshtasticNotifyMessages": "Mag-notify sa mga bagong mensahe",
"defaultMapLayerSettings": "Default na layer ng mapa",
"eewSourceSettings": "Pinagmulan ng EEW",
"eewSourceSubtitle": "Piliin kung aling mga ahensya ang ipapakitang paunang babala sa lindol.",
@@ -454,7 +454,7 @@
"@meshtasticDisconnect": {
"description": "Disconnect from the radio"
},
- "typhoonLabelGust": "Peak gust",
+ "typhoonLabelGust": "Pinakamalakas na bugso",
"mapAppGoogleMaps": "Google Maps",
"sponsorTerms": "Mga Tuntunin ng Paggamit",
"restroomTypeGenderNeutral": "Palikurang neutral sa kasarian",
@@ -463,7 +463,7 @@
},
"notifyThunderstorm": "Mga alerto sa kulog at kidlat",
"skyTimeGolden": "Gintong oras",
- "moonAge": "Age",
+ "moonAge": "Edad ng buwan",
"@windForecastTownOutlineHint": {
"description": "Hint under the township-border toggle in the wind-forecast overlay menu."
},
@@ -481,14 +481,14 @@
},
"language": "Wika",
"homeForecastFeelsLike": "Pakiramdam {temp}°",
- "typhoonOverlayWeatherHint": "Aligned to bulletin time",
+ "typhoonOverlayWeatherHint": "Naka-align sa oras ng bulletin",
"@meshtasticHopLimit": {
"description": "How many hops a packet may take"
},
"skyTimeDawn": "Bukang-liwayway",
"skyTimeAfternoon": "Hapon",
- "meshtasticLastHeard": "Last heard",
- "typhoonWarningTitle": "Typhoon warning",
+ "meshtasticLastHeard": "Huling narinig",
+ "typhoonWarningTitle": "Babala ng bagyo",
"moreSourceCode": "Source code",
"mapLayerCategoryWeather": "Obserbasyon sa panahon",
"mapLayerSatelliteB09": "Himawari Mid Water Vapour (B09)",
@@ -506,20 +506,20 @@
"mapTimelineForecast": "Pagtaya",
"restroomTypeLabel": "Uri",
"navEarthquake": "Lindol",
- "typhoonOverlayStormL10Tooltip": "Level-10 wind field + average circle (yellow)",
- "moonPhaseWaxingGibbous": "Waxing gibbous",
+ "typhoonOverlayStormL10Tooltip": "Larangan ng hangin sa antas 10 + average circle (dilaw)",
+ "moonPhaseWaxingGibbous": "Lumalaking bilog",
"reportDetailTitle": "Ulat ng Lindol",
"moreTremReport": "Ulat ng pagtukoy ng TREM",
"weatherDataTime": "{station} · Oras ng datos {time}",
- "meshtasticNoNodes": "No nodes heard yet",
- "meshtasticViaMqtt": "Via MQTT (internet)",
+ "meshtasticNoNodes": "Wala pang narinig na node",
+ "meshtasticViaMqtt": "Sa pamamagitan ng MQTT (internet)",
"radarCountyOutline": "Mga hangganan ng lalawigan",
"@mapAppCopyCoordinates": {},
"commonClose": "Isara",
"restroomGradeLabel": "Baitang",
"rainIntervalNow": "Ngayon",
"changelogCurrentVersion": "Kasalukuyan",
- "typhoonOverlayForecastCalloutsTooltip": "Show forecast-point detail cards when zoomed in",
+ "typhoonOverlayForecastCalloutsTooltip": "Ipakita ang mga detalye ng forecast point kapag naka-zoom",
"typhoonLabelPressure": "Central pressure",
"aedOpenRemark": "Tala sa oras",
"onboardingPermsBody": "Para maalertuhan ka ng DPIP sa sandaling maganap ang sakuna, mangyaring ibigay ang mga sumusunod. Maaari mo itong baguhin anumang oras sa mga setting ng system.",
@@ -529,14 +529,14 @@
},
"notifyOptWeatherLocal": "Kasalukuyang lokasyon lamang",
"mapNavRain": "Ulan",
- "moonDays": "days",
+ "moonDays": "araw",
"mapLegendUnit": "Yunit: {unit}",
"weatherModeClear": "Maaliwalas",
- "meshtasticRadio": "Radio",
+ "meshtasticRadio": "Radyo",
"commonEmpty": "Walang Maipakita",
"mapLayerSatelliteB01": "Himawari Blue (B01)",
- "meshtasticExternalPower": "External power",
- "moonPhaseLastQuarter": "Last quarter",
+ "meshtasticExternalPower": "Panlabas na kuryente",
+ "moonPhaseLastQuarter": "Huling sangkapat",
"@meshtasticName": {
"description": "The radio's long name"
},
@@ -551,20 +551,20 @@
"mapLayerRestroom": "Pampublikong Palikuran",
"restroomCategoryWelfare": "Institusyon ng kapakanan",
"restroomGradeExcellent": "Napakahusay",
- "meshtasticLastSent": "Last sent",
- "meshtasticName": "Name",
- "meshtasticScan": "Scan",
+ "meshtasticLastSent": "Huling ipinadala",
+ "meshtasticName": "Pangalan",
+ "meshtasticScan": "I-scan",
"@radarOverlayMenuTooltip": {
"description": "Tooltip for the radar overlay-options chip beside the layer switcher"
},
"mapLayerCategoryForecast": "Numerical forecast",
- "meshtasticChannelFailed": "Couldn't set up the DPIP channel",
+ "meshtasticChannelFailed": "Hindi ma-set up ang DPIP channel",
"themeSystem": "Sistema",
"mapLayerSatelliteNdvi": "Himawari NDVI",
"typhoonLegendForecast": "Tinatayang landas",
"typhoonValueHpa": "{n} hPa",
"weatherPrecipitation": "Pag-ulan",
- "moonNextFullMoon": "Next full moon",
+ "moonNextFullMoon": "Susunod na kabilugan",
"dpmSheetEmpty": "I-tap ang marker sa mapa para sa detalye",
"onboardingSkipLeave": "Laktawan pa rin",
"aedPlaceDesc": "Lokasyon ng paglagay",
@@ -582,22 +582,22 @@
},
"onboardingPermBattery": "Exemption sa baterya",
"typhoonLabelNw": "NW",
- "moonPhaseWaxingCrescent": "Waxing crescent",
+ "moonPhaseWaxingCrescent": "Lumalaking gasuklay",
"restroomCategoryLeisure": "Lugar ng libangan",
"mapLayerTemperature": "Temperatura",
"aedCategory": "Kategorya",
"@moonTimelineCaption": {
"description": "Moon phase timeline caption"
},
- "meshtasticChannels": "Channels",
+ "meshtasticChannels": "Mga channel",
"monitorWaiting": "Naghihintay ng data…",
"typhoonOverlayForecastCallouts": "Forecast tooltips",
"@meshtasticTitle": {
"description": "Meshtastic test page title"
},
"reportDetailEpicenter": "Coordinates ng Epicenter",
- "meshtasticVoltage": "Voltage",
- "mapLayerMeshtasticSubtitle": "LoRa mesh nodes heard by your radio",
+ "meshtasticVoltage": "Boltahe",
+ "mapLayerMeshtasticSubtitle": "LoRa mesh nodes na narinig ng radyo mo",
"@meshtasticSent": {
"description": "Packets sent this session"
},
@@ -610,7 +610,7 @@
"rainInterval12h": "12 oras",
"reportListMagnitude": "M{magnitude}",
"notifyMonitor": "Monitor ng malakas na paggalaw",
- "onboardingStart": "Magsimula",
+ "onboardingStart": "Maosmmula",
"@meshtasticExternalPower": {
"description": "Battery value when mains powered"
},
@@ -623,15 +623,15 @@
"description": "Township-border overlay toggle in the map's radar overlay menu."
},
"mapLayerSatelliteB04": "Himawari Near-Infrared (B04)",
- "mapLayerSatelliteTransparentZero": "Zero difference = transparent (no signal)",
+ "mapLayerSatelliteTransparentZero": "Zero difference = transparent (walang signal)",
"shelterIndoorLabel": "Silungan sa loob",
"notifyOptOff": "Naka-off",
"reportFilterSortTime": "Oras",
- "mapLayerSatelliteCloudProbablyClear": "Probably clear",
+ "mapLayerSatelliteCloudProbablyClear": "Malamang maaliwalas",
"weatherModeThunderstorm": "Kulog at Kidlat",
"homeViewOnMap": "Tingnan sa mapa",
"reportFilterIntensityInfoLegacyTitle": "Luma (bago ang 2020)",
- "typhoonLabelSpeed": "Past movement speed",
+ "typhoonLabelSpeed": "Bilis ng paggalaw",
"@meshtasticReconnecting": {
"description": "The link dropped and is being re-established"
},
@@ -640,17 +640,17 @@
"@meshtasticStateDisconnected": {
"description": "Connection state label"
},
- "meshtasticReceived": "Received",
+ "meshtasticReceived": "Natanggap",
"weatherRankingExtremeLow": "Pinakamababa ngayong araw",
"@meshtasticRegionSwitch": {
"description": "Button applying the DPIP LoRa region"
},
"mapLayerSatelliteB10": "Himawari Lower Water Vapour (B10)",
- "mapLayerSatelliteCloudProbablyCloudy": "Probably cloudy",
+ "mapLayerSatelliteCloudProbablyCloudy": "Malamang maulap",
"shelterCategoryLabel": "Mga uri ng kalamidad",
- "mapLayerSatelliteTransparentNoWater": "≤ 0 = transparent (no water)",
- "meshtasticStateConnecting": "Connecting…",
- "moonTitle": "Moon",
+ "mapLayerSatelliteTransparentNoWater": "≤ 0 = transparent (walang tubig)",
+ "meshtasticStateConnecting": "Kumokonekta…",
+ "moonTitle": "Buwan",
"weatherRankingGust": "Bugso",
"moreAppStore": "App Store",
"@meshtasticUndecoded": {
@@ -670,7 +670,7 @@
"regionNationwide": "Buong bansa",
"moreNotifyLog": "Log ng notipikasyon ng DPIP",
"regionCurrent": "Kasalukuyang lokasyon",
- "meshtasticNotConnected": "Not connected to a radio",
+ "meshtasticNotConnected": "Hindi konektado sa radyo",
"weatherModeSnow": "Niyebe",
"mapLayerMeshtastic": "Meshtastic nodes",
"moreDeveloper": "Impormasyon sa debug",
@@ -678,7 +678,7 @@
"description": "Tooltip for the QPESUMS forecast overlay-options chip beside the layer switcher."
},
"mapLayerSatelliteB14": "Himawari Longwave Infrared (B14)",
- "meshtasticChannelUse": "Channel use",
+ "meshtasticChannelUse": "Paggamit ng channel",
"mapNavLightning": "Kidlat",
"homeForecastEmpty": "Walang forecast",
"sponsorOneTime": "Isang beses",
@@ -686,7 +686,7 @@
"onboardingPermBackground": "Lokasyon sa background",
"aedEmergencyPhone": "Emergency phone",
"dpmOpenInMaps": "Buksan sa mapa",
- "meshtasticNotifyNodes": "Notify on new nodes",
+ "meshtasticNotifyNodes": "Mag-notify sa mga bagong node",
"onboardingPermCriticalDesc": "Hayaang tumunog ang mga nakamamatay na babala sa lindol kahit sa silent mode o Do Not Disturb.",
"@mapAppDefault": {
"placeholders": {
@@ -695,11 +695,11 @@
}
}
},
- "mapLayerSatelliteTransparentWarm": "Clear sky (warm end) = transparent, the basemap shows",
- "meshtasticSent": "Sent",
+ "mapLayerSatelliteTransparentWarm": "Maaliwalas (mainit) = transparent, makikita ang basemap",
+ "meshtasticSent": "Ipinadala",
"homeForecastTitle": "24-oras na forecast",
- "typhoonLegendWarningAreas": "Warning areas",
- "meshtasticExcludeMqttHidden": "{count} hidden",
+ "typhoonLegendWarningAreas": "Mga lugar ng babala",
+ "meshtasticExcludeMqttHidden": "{count} nakatago",
"notifyOptLocalIntensity1": "Lokal na intensidad 1 pataas",
"@skyTimeGolden": {
"description": "Label for the skyTimeGolden option in the experimental backdrop settings."
@@ -710,15 +710,15 @@
"mapTimelinePast": "Nakaraan",
"restroomTypeFemale": "Palikuran ng babae",
"reportListToday": "Ngayon",
- "meshtasticTapNode": "Tap a node for details",
+ "meshtasticTapNode": "I-tap ang node para sa detalye",
"commonLoading": "Naglo-load…",
"@meshtasticStateConnecting": {
"description": "Connection state label"
},
- "typhoonIntensityModerate": "Moderate typhoon",
+ "typhoonIntensityModerate": "Katamtamang bagyo",
"mapLayerSatelliteAsh": "Himawari Ash",
"rainInterval3h": "3 oras",
- "meshtasticChannelReady": "DPIP channel ready",
+ "meshtasticChannelReady": "Handa na ang DPIP channel",
"@meshtasticNotifyNodes": {
"description": "Toggle: local notification when a new node is heard"
},
@@ -779,7 +779,7 @@
"description": "Start scanning for Meshtastic radios"
},
"reportDetailDepth": "Lalim ng Hypocenter",
- "typhoonOverlayWarningTooltip": "Highlight counties under a typhoon warning",
+ "typhoonOverlayWarningTooltip": "I-highlight ang mga county sa ilalim ng babala ng bagyo",
"reportFilterDatePick": "Pumili ng petsa",
"onboardingSkipStay": "Bumalik",
"@moonPhaseWaxingCrescent": {
@@ -793,16 +793,16 @@
"description": "Transmit power"
},
"shelterOutdoorLabel": "Silungan sa labas",
- "meshtasticStateConnected": "Connected",
+ "meshtasticStateConnected": "Nakakonekta",
"mapNavRadar": "Radar",
- "mapLayerSatelliteCloudClear": "Clear",
+ "mapLayerSatelliteCloudClear": "Maaliwalas",
"eewSummary": "M{magnitude} · lalim {depth} km",
"locationBannerPermission": "Naka-off ang pahintulot sa lokasyon — hindi matutukoy ng mga lokal na alerto ang iyong lugar.",
- "typhoonOverlayWeatherNoneTooltip": "No radar or infrared underlay",
+ "typhoonOverlayWeatherNoneTooltip": "Walang radar o infrared underlay",
"radarCountyOutlineHint": "Iginuguhit sa ibabaw ng echo",
"windForecastCountyOutlineHint": "Iginuhit sa itaas ng patlang ng hangin",
"homeRainTrendTitle": "Ulan sa susunod na oras",
- "moonPhaseFirstQuarter": "First quarter",
+ "moonPhaseFirstQuarter": "Unang sangkapat",
"mapLayerCategoryTyphoon": "Bagyo",
"@windForecastOverlayMenuTooltip": {
"description": "Tooltip for the wind-forecast overlay-options chip beside the layer switcher."
@@ -816,7 +816,7 @@
"notifyTsunami": "Impormasyon sa tsunami",
"navData": "Datos",
"mapLayerSatelliteBtdWvirw": "Himawari Overshooting Top",
- "meshtasticReadingAge": "Reading taken",
+ "meshtasticReadingAge": "Oras ng pagsukat",
"@moonPhaseWaningGibbous": {
"description": "Phase: waning gibbous"
},
@@ -853,7 +853,7 @@
"trendCumulativeTotal": "Kabuuang {total} mm",
"languageName": "Filipino",
"reportListEmptyFiltered": "Walang ulat na tumutugma sa mga filter",
- "meshtasticExcludeMqtt": "Hide MQTT nodes",
+ "meshtasticExcludeMqtt": "Itago ang mga MQTT node",
"mapNavTyphoon": "Bagyo",
"weatherModeSand": "Alikabok",
"@moonPhaseFirstQuarter": {
@@ -867,11 +867,11 @@
"mapLayerSatelliteB15": "Himawari Longwave Infrared (B15)",
"weatherRankingWind": "Bilis ng hangin",
"feedStale": "Maaaring luma na ang datos",
- "homeForecastWind": "{direction} · Force {level}",
+ "homeForecastWind": "{direction} · Lakas {level}",
"navHome": "Tahanan",
- "meshtasticRegionLabel": "Region",
+ "meshtasticRegionLabel": "Rehiyon",
"mapLayerSatelliteCloudtop": "Himawari Cloud Top Temperature",
- "moonTimelineCaption": "Phase",
+ "moonTimelineCaption": "Porsyento",
"@meshtasticChannelNoSlot": {
"description": "Every secondary channel slot is taken"
},
@@ -900,14 +900,14 @@
"meshtasticAirtime": "Air time (TX)",
"shelterCapacityValue": "{n} katao",
"lightningLegendCc": "Ulap–ulap · {minutes} min",
- "meshtasticSendHint": "Message to broadcast",
+ "meshtasticSendHint": "Mensaheng ipapadala",
"monitorDelay": "Pagkaantala {value} s",
"@meshtasticFirmware": {
"description": "Firmware version"
},
"dpmNo": "Hindi",
"mapLayerSatelliteB08": "Himawari Upper Water Vapour (B08)",
- "meshtasticReconnecting": "Reconnecting…",
+ "meshtasticReconnecting": "Kumokonekta ulit…",
"@mapAppAppleMaps": {},
"@meshtasticReadingAge": {
"description": "How old the battery/airtime numbers are"
@@ -916,7 +916,7 @@
"@moonPhaseWaxingGibbous": {
"description": "Phase: waxing gibbous"
},
- "typhoonOverlayWeatherSatelliteTooltip": "Infrared closest to the typhoon bulletin time",
+ "typhoonOverlayWeatherSatelliteTooltip": "Infrared na pinakamalapit sa oras ng bulletin ng bagyo",
"radarScanRangeHint": "Sa labas: hindi naoobserbahan",
"typhoonPickerTd": "Tropical depression TD {no}",
"mapLayerSatelliteWatervapor": "Himawari Water Vapour",
@@ -925,7 +925,7 @@
"restroomGradePoor": "Mas mababa sa pamantayan",
"restroomCategoryTourist": "Lugar para sa turista",
"locationBannerServiceOff": "Naka-off ang mga serbisyo ng lokasyon — hindi matutukoy ng mga lokal na alerto ang iyong lugar.",
- "mapLayerStyleTooltip": "Colour style",
+ "mapLayerStyleTooltip": "Estilo ng kulay",
"lightningLegendCg": "Ulap–lupa · {minutes} min",
"skyTimeAuto": "Awtomatiko",
"appLogs": "Mga log ng app",
@@ -969,18 +969,18 @@
"endpointServiceRadar": "Radar",
"endpointServiceSatellite": "Satellite",
"endpointServiceQpesums": "QPE",
- "endpointServiceWind": "Wind",
+ "endpointServiceWind": "Hangin",
"endpointServiceDpm": "Disaster points",
- "endpointServiceWeather": "Weather",
- "endpointServiceRain": "Rain",
- "endpointServiceLightning": "Lightning",
- "endpointServiceTyphoon": "Typhoon",
- "endpointServiceReport": "EQ reports",
+ "endpointServiceWeather": "Panahon",
+ "endpointServiceRain": "Ulan",
+ "endpointServiceLightning": "Kidlat",
+ "endpointServiceTyphoon": "Bagyo",
+ "endpointServiceReport": "Mga ulat ng lindol",
"endpointServiceTremStation": "Tremor station",
- "endpointServiceEvent": "Events",
- "endpointServiceLocation": "Location",
- "endpointServiceNotify": "Notifications",
- "endpointServiceOther": "Other",
+ "endpointServiceEvent": "Mga event",
+ "endpointServiceLocation": "Lokasyon",
+ "endpointServiceNotify": "Mga notipikasyon",
+ "endpointServiceOther": "Iba pa",
"feedConnecting": "Kumokonekta…",
"notifyBannerDisabled": "Naka-off ang mga notification — hindi ka makakatanggap ng mga alerto sa sakuna.",
"@meshtasticNoNodes": {
@@ -989,33 +989,34 @@
"weatherHumidity": "Halumigmig",
"typhoonValueMs": "{n} m/s",
"homeForecastHumidity": "Halumigmig {value}%",
- "meshtasticBusyBody": "Disconnect it in the other Meshtastic app first. Two apps on one radio take each other's messages, so some will go missing.",
- "meshtasticChannelNoSlot": "No free channel slot — free one on the radio",
+ "meshtasticBusyBody": "I-disconnect muna ito sa ibang Meshtastic app. Dalawang app sa isang radyo ang nag-aagawan sa mensahe, kaya may mawawala.",
+ "meshtasticChannelNoSlot": "Walang libreng channel slot — magbakante sa radyo",
"restroomCategoryTransport": "Transportasyon",
- "meshtasticBattery": "Battery",
+ "meshtasticBattery": "Baterya",
"meshtasticDistance": "Distansya",
"meshtasticSnrTrend": "Trend ng signal (SNR)",
"meshtasticBatteryTrend": "Trend ng baterya",
- "typhoonOverlayMenuTooltip": "Typhoon overlay options",
+ "typhoonOverlayMenuTooltip": "Mga opsyon sa typhoon overlay",
"mapLayerSatelliteBtdOzone": "Himawari Tropopause",
- "meshtasticRegionMismatch": "Radio region is {region} — DPIP needs TW",
+ "meshtasticRegionMismatch": "Ang region ng radyo ay {region} — kailangan ng DPIP ang TW",
"notifySectionEarthquake": "Lindol",
"mapLayerDisasterMap": "Disaster Map",
"weatherModeFog": "Makapal na Hamog",
"typhoonPickerNamed": "{name} TY {no}",
- "mapLayerStyleGrayTooltip": "JMA grayscale — colder is whiter",
+ "mapLayerStyleGrayTooltip": "JMA grayscale — mas malamig ay mas puti",
"moreAnnouncements": "Mga Anunsyo",
"moreTagline": "Platform para sa Integral na Impormasyon sa Kalamidad",
"moreVersionStable": "Pormal na bersyon",
- "moreVersionNotes": "Kasalukuyang bersyon",
+ "moreVersionNotes": "Update na ito",
+ "moreVersionNotesHighlightsSubtitle": "Ano ang nagbago sa bersyon na ito",
"releaseHighlightsSeeNotes": "Buong tala ng release",
- "releaseHighlightsTitle": "Ano ang nagbago",
+ "releaseHighlightsTitle": "{train} buod",
"releaseHighlightsTabNormal": "Para sa mga user",
"releaseHighlightsTabAdvanced": "Mas malalim",
"releaseHighlightsEmpty": "Wala pang laman.",
"moreVersionNotesEmpty": "Walang changelog para sa build na ito",
"moreVersionSnapshot": "Bersyon ng pagsubok",
- "mapLayerSatelliteTransparentNoData": "No data (land) = transparent",
+ "mapLayerSatelliteTransparentNoData": "Walang data (lupa) = transparent",
"@meshtasticScanning": {
"description": "Scan in progress"
},
@@ -1025,7 +1026,7 @@
"mapLayerAed": "AED",
"changelogTypePrerelease": "Beta",
"reportFilterIntensityInfoModernBody": "Antas 0–4, 5−, 5+, 6−, 6+, 7. Gamit ng filter ang bagong scale; ang mga lumang event ay may legacy label sa listahan.",
- "typhoonOverlayWeatherNone": "None",
+ "typhoonOverlayWeatherNone": "Wala",
"mapLayerStyleGray": "Grayscale (JMA)",
"weatherModeAuto": "Awtomatiko",
"typhoonLabelProbCircle": "70% probability circle",
@@ -1038,7 +1039,7 @@
"@skyTimeSunrise": {
"description": "Label for the skyTimeSunrise option in the experimental backdrop settings."
},
- "typhoonLabelDirection": "Past movement direction",
+ "typhoonLabelDirection": "Direksyon ng paggalaw",
"@meshtasticLastSent": {
"description": "Age of the last sent packet"
},
@@ -1052,13 +1053,13 @@
"onboardingPermsTitle": "Mga Pahintulot",
"mapLayerStyleJma": "Cloud-top enhancement (JMA)",
"rainInterval10m": "10 min",
- "meshtasticConnectAnyway": "Connect anyway",
+ "meshtasticConnectAnyway": "Kumonekta pa rin",
"reportListDayCount": "{count}",
"mapLayerSatelliteB06": "Himawari Near-Infrared (B06)",
- "mapLayerSatelliteTransparentReflectance": "Low reflectance / night = transparent, the basemap shows",
+ "mapLayerSatelliteTransparentReflectance": "Mababang reflectance / gabi = transparent, makikita ang basemap",
"chartHourLabel": "{hour}h",
"mapLayerShelter": "Silungan",
- "typhoonOverlayProbabilityTooltip": "Show strike probability (hides the forecast cone)",
+ "typhoonOverlayProbabilityTooltip": "Ipakita ang strike probability (itinatago ang forecast cone)",
"mapLayerSatelliteNdwi": "Himawari NDWI",
"disasterMapOverlayShelterTooltip": "Ipakita ang mga silungan",
"mapNavHumidity": "Halumigmig",
@@ -1068,7 +1069,7 @@
"reportDetailSortByIntensity": "Ayusin ayon sa intensity",
"homeRainTrendNoData": "Walang data",
"mapLayerCategoryRadar": "Radar",
- "meshtasticShortName": "Short name",
+ "meshtasticShortName": "Maikling pangalan",
"@meshtasticStateConfiguring": {
"description": "Connection state label"
},
@@ -1088,7 +1089,7 @@
"@skyTimeMorning": {
"description": "Label for the skyTimeMorning option in the experimental backdrop settings."
},
- "meshtasticRegionConfirm": "Switch this radio to the TW region? It restarts and disconnects for a moment, and every other channel on it moves too.",
+ "meshtasticRegionConfirm": "Lumipat ba ang radyong ito sa TW region? Magre-restart at magdi-disconnect saglit, at lilipat din ang lahat ng ibang channel.",
"dataEarthquakeSubtitle": "Mga ulat ng lindol",
"typhoonNoActive": "Walang aktibong bagyo",
"@meshtasticExcludeMqttHidden": {
@@ -1105,10 +1106,55 @@
"@meshtasticChannels": {
"description": "Section: the radio's channel table"
},
+ "mapOsmOverlay": "Detalyadong mapa",
+ "mapOsmOverlayHint": "Ipakita ang mas kumpletong mga kalsada, gusali, at pangalan ng lugar",
+ "mapOsmDetails": "Mga detalye ng layer",
+ "moreDataSources": "Mga pinagmulan ng data",
+ "dataSourceTremNet": "探索智慧科技有限公司 — TREM-Net",
+ "dataSourceCwa": "交通部中央氣象署 (CWA)",
+ "dataSourceJma": "気象庁 (JMA)",
+ "dataSourceNcdr": "國家災害防救科技中心 (NCDR)",
+ "dataSourceEcmwf": "European Centre for Medium-Range Weather Forecasts (ECMWF)",
+ "dataSourceNoaaGfs": "National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)",
+ "dataSourceGovernmentOpenData": "政府資料開放平臺",
+ "dataSourceOpenStreetMap": "© OpenStreetMap contributors",
+ "dataSourceNasaMoon": "National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)",
+ "mapOsmDetailsHint": "{enabled} sa {total} na layer ang naka-enable",
+ "@mapOsmDetailsHint": {
+ "description": "How many of the OSM layers are enabled",
+ "placeholders": {
+ "enabled": {
+ "type": "int"
+ },
+ "total": {
+ "type": "int"
+ }
+ }
+ },
+ "mapOsmSurface": "Ibabaw",
+ "mapOsmParks": "Mga parke",
+ "mapOsmLandUse": "Paggamit ng lupa",
+ "mapOsmAirportAreas": "Mga lugar ng paliparan",
+ "mapOsmWater": "Tubig",
+ "mapOsmRivers": "Mga ilog",
+ "mapOsmBoundaries": "Mga hangganan",
+ "mapOsmBuildings": "Mga gusali",
+ "mapOsmRoads": "Mga kalsada",
+ "mapOsmRoadNames": "Pangalan ng kalsada",
+ "mapOsmWaterNames": "Pangalan ng tubig",
+ "mapOsmPeaks": "Mga taluktok",
+ "mapOsmAirportNames": "Pangalan ng paliparan",
+ "mapOsmPlaceNames": "Pangalan ng lugar",
+ "mapOsmPoi": "Mga lugar ng interes",
+ "mapOsmHouseNumbers": "Mga numero ng bahay",
+ "mapOsmRestoreAll": "Ibalik lahat",
+ "mapOsmSectionNatural": "Mga likas na anyo",
+ "mapOsmSectionRoadsAndBuildings": "Mga kalsada at gusali",
+ "mapOsmSectionLabelsAndPlaces": "Mga label at lugar",
"mapTownLabels": "Mga pangalan ng bayan",
"notifySetFailed": "Hindi ma-save ang setting. Pakisubukan muli.",
- "meshtasticDisconnect": "Disconnect",
- "meshtasticUndecoded": "Not decrypted",
+ "meshtasticDisconnect": "I-disconnect",
+ "meshtasticUndecoded": "Hindi nade-decrypt",
"notifyAnnouncement": "Mga Anunsyo",
"onboardingIntroTitle": "Maligayang pagdating sa DPIP",
"regionCurrentUnavailable": "Hindi makuha ang kasalukuyang lokasyon",
@@ -1126,7 +1172,7 @@
"@moonSectionAppearance": {
"description": "Section header: how the Moon looks at the chosen moment"
},
- "moonSectionRiseSet": "Pagsikat at paglubog",
+ "moonSectionRiseSet": "Paosmkat at paglubog",
"@moonSectionRiseSet": {
"description": "Section header: moonrise and moonset for the user's township"
},
@@ -1150,7 +1196,7 @@
"@moonApparentSize": {
"description": "The Moon's apparent angular diameter"
},
- "moonRise": "Pagsikat ng buwan",
+ "moonRise": "Paosmkat ng buwan",
"@moonRise": {
"description": "Time the Moon rises"
},
@@ -1194,7 +1240,7 @@
"@sunSectionTerms": {
"description": "Section header: the year's twenty-four solar terms"
},
- "sunRise": "Pagsikat ng araw",
+ "sunRise": "Paosmkat ng araw",
"@sunRise": {
"description": "Time the Sun rises"
},
@@ -1410,7 +1456,7 @@
"@solarTermMajorCold": {
"description": "One of the twenty-four solar terms"
},
- "solarTermStartOfSpring": "Simula ng Tagsibol",
+ "solarTermStartOfSpring": "Simula ng Taosmbol",
"@solarTermStartOfSpring": {
"description": "One of the twenty-four solar terms"
},
@@ -1799,6 +1845,30 @@
"description": "Button that opens the system settings page"
},
"permissionSettingsMessage": "Tinanggihan ang “{what}” at hindi na magtatanong ang sistema. I-on ito sa Settings.",
+ "permissionGuideNotification": "Buksan ang System Settings upang payagan ang mga notipikasyon.",
+ "permissionGuideForegroundLocation": "Buksan ang System Settings upang payagan ang tumpak na lokasyon.",
+ "permissionGuideBackgroundLocation": "Sa “{option}”, piliin ang “Payagan sa lahat ng oras”.",
+ "@permissionGuideBackgroundLocation": {
+ "description": "Instruction for background location",
+ "placeholders": {
+ "option": {}
+ }
+ },
+ "permissionGuideBackgroundExecution": "Payagan ang background execution sa System Settings upang hindi i-pause ang mga notipikasyon.",
+ "permissionGuideUnusedPause": "Kung minarkahan ang app na “hindi ginagamit”, piliin ang “Payagan” sa System Settings.",
+ "permissionGuideUnusedFreeSpace": "Kung na-pause ang app dahil sa storage, i-clear ang cache at buksan muli.",
+ "permissionGuideUnusedRevoke": "Kung binawi ang mga pahintulot ng app, ibigay muli sa System Settings.",
+ "permissionGuideUnusedPlayProtect": "Kung i-pause ng Play Protect ang app, tingnan ang katayuan nito sa Google Play.",
+ "permissionGuideVendorPower": "Sa mga setting ng pagtitipid ng kuryente ng “{vendor}”, itakda ang app na ito sa “Walang limitasyon”.",
+ "@permissionGuideVendorPower": {
+ "description": "Instruction for vendor power saving",
+ "placeholders": {
+ "vendor": {}
+ }
+ },
+ "permissionStillRequired": "Kailangan pa rin — buksan ang Settings para paganahin.",
+ "permissionVerifyManually": "Mangyaring i-verify nang manu-mano na naka-enable ang pahintulot na ito sa System Settings.",
+ "permissionBackgroundLocationOption": "“Payagan sa lahat ng oras”",
"@permissionSettingsMessage": {
"description": "Explains that the system will not ask again for this permission",
"placeholders": {
@@ -1872,6 +1942,9 @@
},
"moreDumpDiagnostics": "I-upload ang debug info at mga log",
"moreDumpDiagnosticsHint": "Iuupload at kokopyahin ang link para ilakip sa ulat",
+ "dumpIncludeSensitive": "Isama ang eksaktong lokasyon",
+ "dumpIncludeSensitiveHint": "Isinasama ang mga coordinate mula sa log at lokasyon sa background; kapag hindi pinili, papalitan ng null",
+ "dumpUpload": "I-upload",
"dumpUploaded": "Na-upload",
"dumpLinkCopied": "Nakopya ang link sa clipboard",
"dumpCopyAgain": "Kopyahin ulit",
diff --git a/lib/l10n/app_id.arb b/lib/l10n/app_id.arb
index 30e024bb1..cbfffcf4a 100644
--- a/lib/l10n/app_id.arb
+++ b/lib/l10n/app_id.arb
@@ -19,29 +19,29 @@
"reportFilterIntensity": "Intensitas",
"mapLayerLightning": "Petir",
"restroomTypeMale": "Toilet pria",
- "meshtasticLastReceived": "Last received",
+ "meshtasticLastReceived": "Terakhir diterima",
"reportDetailSortByCounty": "Urutkan menurut wilayah",
"@moonDays": {
"description": "Day unit for the moon age"
},
"homeRainTrendScattered": "Kemungkinan hujan ringan",
- "meshtasticUptime": "Uptime",
+ "meshtasticUptime": "Waktu aktif",
"weatherRankingTempExtremes": "Ekstrem suhu",
"themeLight": "Terang",
"mapTerrainReliefHint": "Tampilkan relief terrain di peta dasar",
- "meshtasticEmptyMessage": "(empty message)",
+ "meshtasticEmptyMessage": "(pesan kosong)",
"moreSectionRegion": "Wilayah",
"mapLayerSatellite": "Himawari Infrared (B13)",
"@meshtasticTapNode": {
"description": "Resting state of the map node sheet"
},
"aedHoursSaturday": "Jam Sabtu",
- "moonPhaseNew": "New moon",
+ "moonPhaseNew": "Bulan baru",
"notifySectionEew": "Peringatan dini gempa",
"mapResetNorth": "Kembali ke utara",
"rainInterval2d": "2 hr",
"mapTownLabelsHint": "Tampilkan nama kecamatan saat diperbesar",
- "commonCancel": "Cancel",
+ "commonCancel": "Batal",
"notifyOptTsunamiWarning": "Hanya peringatan tsunami",
"mapLayerSatelliteBtdFog": "Himawari Night Fog",
"@meshtasticSelectDevice": {
@@ -59,7 +59,7 @@
"notifySettingsMenu": "Pengaturan notifikasi",
"mapAppDefault": "{app} (bawaan)",
"trendRange24h": "24 jam",
- "mapLayerStyleJmaTooltip": "Grayscale base, tinted below −40 °C to highlight cloud-top height",
+ "mapLayerStyleJmaTooltip": "Basis grayscale, diwarnai di bawah −40 °C untuk menyorot tinggi puncak awan",
"mapLayerRain": "Curah hujan",
"mapLayerQpesums": "Prakiraan hujan 1 jam ke depan",
"@weatherModeSnow": {
@@ -82,16 +82,16 @@
"changelogShowSnapshots": "Tampilkan snapshot",
"changelogTitle": "Catatan pembaruan",
"reportFilterOrderDesc": "Menurun",
- "meshtasticExcludeMqttSubtitle": "Nodes bridged over the internet, not heard by radio",
+ "meshtasticExcludeMqttSubtitle": "Node yang terhubung lewat internet, tidak terdengar lewat radio",
"reportFilterIntensityInfoTitle": "Skala intensitas baru & lama",
"mapLayerTyphoon": "Topan",
"radarOverlayMenuTooltip": "Opsi lapisan radar",
"@meshtasticChannelUse": {
"description": "Share of airtime seen busy"
},
- "meshtasticNodes": "Nodes",
- "meshtasticSend": "Send",
- "typhoonOverlayStormL7Tooltip": "Level-7 wind field + average circle (purple)",
+ "meshtasticNodes": "Node",
+ "meshtasticSend": "Kirim",
+ "typhoonOverlayStormL7Tooltip": "Medan angin level 7 + lingkaran rata-rata (ungu)",
"aedType": "Jenis",
"termsOfService": "Ketentuan Layanan",
"typhoonLegendCircle25": "Lingkar badai",
@@ -115,7 +115,7 @@
"description": "Map layer name: mesh nodes"
},
"reportFilterDateEndNote": "Hari akhir: hingga 24:00(Taipei)",
- "meshtasticSilent": "Silent",
+ "meshtasticSilent": "Senyap",
"reportFilterSortMagnitude": "Magnitudo",
"mapLayerCategoryEarthquake": "Gempa",
"mapLayerSatelliteB12": "Himawari Ozone (B12)",
@@ -144,12 +144,12 @@
"@radarCountyOutlineHint": {
"description": "Hint under the county-border toggle in the radar overlay menu."
},
- "meshtasticLayerOptions": "Node options",
+ "meshtasticLayerOptions": "Opsi node",
"onboardingAgreeContinue": "Setuju dan lanjutkan",
- "meshtasticNodeId": "Node ID",
+ "meshtasticNodeId": "ID Node",
"commonRetry": "Coba lagi",
"reportDetailNumbered": "Gempa Dirasakan Signifikan No. {number}",
- "typhoonOverlayStormBandSubtitle": "With average circle",
+ "typhoonOverlayStormBandSubtitle": "Dengan lingkaran rata-rata",
"disasterMapOverlayRestroomTooltip": "Tampilkan toilet umum",
"weatherRankingTitle": "Peringkat observasi",
"homeRainTrendHeavySustained": "Hujan deras berlanjut selama 1 jam ke depan",
@@ -161,12 +161,12 @@
"@meshtasticSilent": {
"description": "Legend: node known but not heard recently"
},
- "meshtasticChannelWorking": "Setting up the DPIP channel…",
- "meshtasticRegionSwitch": "Switch to TW",
+ "meshtasticChannelWorking": "Menyiapkan kanal DPIP…",
+ "meshtasticRegionSwitch": "Beralih ke TW",
"@meshtasticLastReceived": {
"description": "Age of the last received packet"
},
- "meshtasticTraffic": "Traffic",
+ "meshtasticTraffic": "Lalu lintas",
"@meshtasticDpipChannel": {
"description": "Which channel DPIP payloads use"
},
@@ -176,8 +176,8 @@
"description": "Moon page title"
},
"mapLayerHumidity": "Kelembapan",
- "mapLayerSatelliteTransparentNight": "Night = transparent, the basemap shows",
- "meshtasticScanning": "Scanning…",
+ "mapLayerSatelliteTransparentNight": "Malam = transparan, peta dasar terlihat",
+ "meshtasticScanning": "Memindai…",
"@meshtasticDevice": {
"description": "Section: device identity"
},
@@ -202,7 +202,7 @@
"meshtasticEtaDays": "~{n} hari",
"meshtasticTitle": "Meshtastic",
"navMore": "Lainnya",
- "meshtasticDpipChannel": "DPIP channel",
+ "meshtasticDpipChannel": "Kanal DPIP",
"disasterMapOverlaySectionLayers": "Lapisan",
"@moonPhaseWaningCrescent": {
"description": "Phase: waning crescent"
@@ -215,15 +215,15 @@
"description": "Label for the weatherModeCloudy option in the experimental backdrop settings."
},
"typhoonLabelNe": "NE",
- "meshtasticCopied": "Message copied",
+ "meshtasticCopied": "Pesan disalin",
"reportListEmpty": "Tidak ada laporan gempa",
"reportListEnd": "Akhir daftar",
"mapLayerSatelliteTruecolor": "Himawari True Color",
- "typhoonOverlaySectionExtra": "Overlays",
+ "typhoonOverlaySectionExtra": "Lapisan tambahan",
"eewSWave": "Gelombang S",
- "meshtasticBusyTitle": "Another app is using this radio",
+ "meshtasticBusyTitle": "Aplikasi lain sedang menggunakan radio ini",
"restroomCategoryCultural": "Tempat budaya",
- "typhoonLabelWind": "Max. sustained wind near centre",
+ "typhoonLabelWind": "Angin bertahan maks. dekat pusat",
"radarGlobalOutlineHint": "Bingkai luar setiap negara",
"notifyEvacuation": "Informasi bencana",
"typhoonLegendCircle15": "Lingkar angin kencang",
@@ -233,11 +233,11 @@
"@meshtasticRadioSettings": {
"description": "Section: LoRa settings"
},
- "dataSectionAstronomy": "Astronomy",
+ "dataSectionAstronomy": "Astronomi",
"homeRainTrendLightSustained": "Hujan ringan berlanjut selama 1 jam ke depan",
"commonError": "Terjadi kesalahan",
- "moonPhaseWaningCrescent": "Waning crescent",
- "meshtasticPower": "Power",
+ "moonPhaseWaningCrescent": "Bulan sabit memudar",
+ "meshtasticPower": "Daya",
"@meshtasticChannelWorking": {
"description": "Creating/verifying the DPIP channel"
},
@@ -248,14 +248,14 @@
"typhoonWarningAreas": "Wilayah: {areas}",
"rainIntervalSection": "Jendela waktu",
"notifyTitle": "Notifikasi",
- "meshtasticTxPower": "TX power",
+ "meshtasticTxPower": "Daya TX",
"@radarTownOutlineHint": {
"description": "Hint under the township-border toggle in the radar overlay menu."
},
"restroomCategoryLabel": "Kategori",
"sponsorRestoring": "Memulihkan pembelian…",
"sponsorIntro": "DPIP berdedikasi menyediakan informasi mitigasi bencana secara real-time, tanpa iklan atau model bisnis lainnya. Dukungan Anda membantu kami menjaga server tetap berjalan dan terus mengembangkan aplikasi.",
- "typhoonLabelStormAvg": "Avg. radius of Beaufort 10 winds",
+ "typhoonLabelStormAvg": "Jari-jari rata-rata angin Beaufort 10",
"@meshtasticHardware": {
"description": "Board model"
},
@@ -274,8 +274,8 @@
"rainInterval6h": "6 jam",
"homeRainTrendMinute": "{minute} mnt",
"restroomTypeUnspecified": "Tidak ditentukan",
- "typhoonOverlayProbabilityHint": "Hides the forecast cone",
- "mapLayerSatelliteGlobalOutline": "Country border",
+ "typhoonOverlayProbabilityHint": "Menyembunyikan kerucut prakiraan",
+ "mapLayerSatelliteGlobalOutline": "Batas negara",
"mapNavTemperature": "Suhu",
"typhoonLegendForecastPoint": "Titik prakiraan",
"@meshtasticBattery": {
@@ -289,16 +289,16 @@
"rainInterval3d": "3 hr",
"defaultMapLayerSubtitle": "Tab Peta membuka lapisan ini. Ikon dan label navigasi bawah ikut pilihan ini.",
"aedDescription": "Catatan",
- "typhoonOverlayWeatherRadarTooltip": "Radar echo closest to the typhoon bulletin time",
+ "typhoonOverlayWeatherRadarTooltip": "Gema radar terdekat dengan waktu buletin topan",
"onboardingPermLocationDesc": "Menargetkan peringatan ke lokasi Anda.",
"mapLayerSatelliteB16": "Himawari CO₂ (B16)",
"@meshtasticClearMessages": {
"description": "Menu action clearing the message log"
},
"homeActiveEventsEmpty": "Tidak ada peristiwa aktif",
- "typhoonLabelPosition": "Centre location",
+ "typhoonLabelPosition": "Lokasi pusat",
"weatherRankingBy": "Urut",
- "typhoonIntensityMild": "Mild typhoon",
+ "typhoonIntensityMild": "Topan lemah",
"windForecastGlobalOutlineHint": "Bingkai luar setiap negara",
"rainInterval1h": "1 jam",
"eewLocalIntensity": "Perkiraan di lokasi",
@@ -307,31 +307,31 @@
"description": "Radar scan-range overlay toggle in the map's radar overlay menu."
},
"restroomCategoryReligious": "Tempat ibadah",
- "meshtasticRole": "Role",
+ "meshtasticRole": "Peran",
"mapLayerSatelliteCloudCloudy": "Cloudy",
"skyTimeSunrise": "Matahari terbit",
"@mapLayerMeshtasticSubtitle": {
"description": "Map layer switcher subtitle"
},
"meshtasticJumpToLatest": "Ke yang terbaru",
- "meshtasticNoMessages": "No messages yet",
+ "meshtasticNoMessages": "Belum ada pesan",
"onboardingPermNotifyDesc": "Menyampaikan peringatan gempa, cuaca, dan bencana pada saat terjadi.",
"radarTownOutline": "Batas kecamatan",
- "mapLayerStyleSection": "Colour style",
+ "mapLayerStyleSection": "Gaya warna",
"@moonPhaseNew": {
"description": "Phase: new moon"
},
"disasterMapOverlayMenuTooltip": "Lapisan peta bencana",
"moreGooglePlay": "Google Play",
- "meshtasticOnline": "Heard recently",
+ "meshtasticOnline": "Baru terdengar",
"@meshtasticSendHint": {
"description": "Message input hint"
},
"typhoonLabelSw": "SW",
- "typhoonForecastLead": "Forecast +{hours} h",
+ "typhoonForecastLead": "Prakiraan +{hours} jam",
"@mapAppOpenFailed": {},
"changelogTypeStable": "Stabil",
- "mapLayerSatelliteTransparentClear": "Clear sky = transparent, the basemap shows",
+ "mapLayerSatelliteTransparentClear": "Langit cerah = transparan, peta dasar terlihat",
"@skyTimeAuto": {
"description": "Label for the skyTimeAuto option in the experimental backdrop settings."
},
@@ -350,11 +350,11 @@
"mapLayerSatelliteTransparentNoVegetation": "Below 0.1 = transparent (no vegetation)",
"notifyOptLocalIntensity4": "Intensitas lokal 4 atau lebih",
"eewArrived": "Tiba",
- "meshtasticNoDevices": "No Meshtastic devices found",
+ "meshtasticNoDevices": "Tidak menemukan perangkat Meshtastic",
"mapLayerCategoryLife": "Kehidupan sehari-hari",
"reportFilterSortIntensity": "Intensitas",
- "meshtasticStateDisconnected": "Disconnected",
- "typhoonIntensityIntense": "Intense typhoon",
+ "meshtasticStateDisconnected": "Terputus",
+ "typhoonIntensityIntense": "Topan kuat",
"@meshtasticSend": {
"description": "Send message button"
},
@@ -366,7 +366,7 @@
"description": "The radio's short name"
},
"dpmYes": "Ya",
- "meshtasticNoHistory": "Not enough history yet",
+ "meshtasticNoHistory": "Riwayat belum cukup",
"reportDetailLocalIntensityUnavailable": "Tidak ada data intensitas",
"mapLayerWindForecastGfs": "GFS",
"reportFilterDepth": "Kedalaman",
@@ -388,10 +388,10 @@
"@meshtasticNoMessages": {
"description": "Empty message log while connected"
},
- "reportFilterReset": "Reset",
+ "reportFilterReset": "Atur ulang",
"mapLayerSatelliteMndwi": "Himawari MNDWI",
- "typhoonOverlaySectionStorm": "Storm wind",
- "moonPhaseFull": "Full moon",
+ "typhoonOverlaySectionStorm": "Angin badai",
+ "moonPhaseFull": "Bulan purnama",
"@meshtasticEmptyMessage": {
"description": "Placeholder for a text packet with no body"
},
@@ -399,24 +399,24 @@
"@radarGlobalOutlineHint": {
"description": "Hint under the national-border toggle in the radar overlay menu."
},
- "moonPhaseWaningGibbous": "Waning gibbous",
+ "moonPhaseWaningGibbous": "Bulan cembung memudar",
"reportFilterIntensityInfoModernTitle": "Baru (sejak 2020)",
"@mapAppGoogleMaps": {},
- "typhoonDataTime": "Data time\n{time}",
+ "typhoonDataTime": "Waktu data",
"restroomTypeAccessible": "Toilet aksesibel",
"moreSectionAbout": "Tentang",
- "meshtasticSelectDevice": "Select a radio",
+ "meshtasticSelectDevice": "Pilih radio",
"onboardingIntroBody": "DPIP adalah pendamping pencegahan bencana Anda. DPIP menyatukan peringatan dini gempa, laporan gempa, cuaca, dan informasi bahaya, serta memberi tahu Anda pada saat yang penting.\n\n• Gempa bumi: peringatan dini, laporan intensitas, dan laporan rinci\n• Cuaca: pesan badai petir waktu nyata dan imbauan cuaca\n• Tsunami dan informasi bencana\n\nSelanjutnya, kami akan meminta Anda meninjau Ketentuan Layanan dan memberikan beberapa izin agar DPIP dapat melindungi Anda secara waktu nyata.",
"shelterCapacityLabel": "Kapasitas",
"reportDetailImage": "Gambar laporan",
- "meshtasticStateConfiguring": "Configuring…",
+ "meshtasticStateConfiguring": "Mengonfigurasi…",
"@moonPhaseLastQuarter": {
"description": "Phase: last quarter"
},
- "typhoonLabelGaleAvg": "Avg. radius of Beaufort 7 winds",
+ "typhoonLabelGaleAvg": "Jari-jari rata-rata angin Beaufort 7",
"onboardingPermNotify": "Notifikasi",
- "meshtasticClearMessages": "Clear messages",
- "meshtasticNotifyMessages": "Notify on new messages",
+ "meshtasticClearMessages": "Hapus pesan",
+ "meshtasticNotifyMessages": "Beri tahu saat pesan baru",
"defaultMapLayerSettings": "Lapisan peta bawaan",
"eewSourceSettings": "Sumber EEW",
"eewSourceSubtitle": "Pilih badan penerbit peringatan dini gempa yang ingin ditampilkan.",
@@ -446,7 +446,7 @@
"description": "Label for the skyTimeAfternoon option in the experimental backdrop settings."
},
"mapTimelineFuture": "Mendatang",
- "typhoonLegendCircleAvg": "Average circle",
+ "typhoonLegendCircleAvg": "Lingkaran rata-rata",
"reportFilterDepthKm": "{depth} km",
"typhoonLabelSe": "SE",
"radarTownOutlineHint": "Kisi yang lebih rapat",
@@ -454,7 +454,7 @@
"@meshtasticDisconnect": {
"description": "Disconnect from the radio"
},
- "typhoonLabelGust": "Peak gust",
+ "typhoonLabelGust": "Embusan puncak",
"mapAppGoogleMaps": "Google Maps",
"sponsorTerms": "Ketentuan Penggunaan",
"restroomTypeGenderNeutral": "Toilet netral gender",
@@ -463,7 +463,7 @@
},
"notifyThunderstorm": "Peringatan badai petir",
"skyTimeGolden": "Jam emas",
- "moonAge": "Age",
+ "moonAge": "Umur bulan",
"@windForecastTownOutlineHint": {
"description": "Hint under the township-border toggle in the wind-forecast overlay menu."
},
@@ -474,20 +474,20 @@
"moreGithub": "ExpTech GitHub",
"homeForecastUnavailable": "Pilih wilayah untuk melihat prakiraan",
"mapLayers": "Lapisan",
- "meshtasticHardware": "Hardware",
+ "meshtasticHardware": "Perangkat keras",
"languageSettings": "Bahasa",
"@moonNextFullMoon": {
"description": "Next full moon date label"
},
"language": "Bahasa",
"homeForecastFeelsLike": "Terasa {temp}°",
- "typhoonOverlayWeatherHint": "Aligned to bulletin time",
+ "typhoonOverlayWeatherHint": "Diselaraskan dengan waktu buletin",
"@meshtasticHopLimit": {
"description": "How many hops a packet may take"
},
"skyTimeDawn": "Fajar",
"skyTimeAfternoon": "Sore",
- "meshtasticLastHeard": "Last heard",
+ "meshtasticLastHeard": "Terakhir terdengar",
"typhoonWarningTitle": "Peringatan topan",
"moreSourceCode": "Kode sumber",
"mapLayerCategoryWeather": "Pengamatan cuaca",
@@ -506,37 +506,37 @@
"mapTimelineForecast": "Prakiraan",
"restroomTypeLabel": "Jenis",
"navEarthquake": "Gempa Bumi",
- "typhoonOverlayStormL10Tooltip": "Level-10 wind field + average circle (yellow)",
- "moonPhaseWaxingGibbous": "Waxing gibbous",
+ "typhoonOverlayStormL10Tooltip": "Medan angin level 10 + lingkaran rata-rata (kuning)",
+ "moonPhaseWaxingGibbous": "Bulan cembung membesar",
"reportDetailTitle": "Laporan Gempa",
"moreTremReport": "Laporan deteksi TREM",
"weatherDataTime": "{station} · Waktu data {time}",
- "meshtasticNoNodes": "No nodes heard yet",
- "meshtasticViaMqtt": "Via MQTT (internet)",
+ "meshtasticNoNodes": "Belum ada node yang terdengar",
+ "meshtasticViaMqtt": "Lewat MQTT (internet)",
"radarCountyOutline": "Batas kabupaten/kota",
"@mapAppCopyCoordinates": {},
"commonClose": "Tutup",
"restroomGradeLabel": "Nilai",
"rainIntervalNow": "Hari ini",
"changelogCurrentVersion": "Saat ini",
- "typhoonOverlayForecastCalloutsTooltip": "Show forecast-point detail cards when zoomed in",
- "typhoonLabelPressure": "Central pressure",
+ "typhoonOverlayForecastCalloutsTooltip": "Tampilkan kartu detail titik prakiraan saat diperbesar",
+ "typhoonLabelPressure": "Tekanan pusat",
"aedOpenRemark": "Catatan jam buka",
"onboardingPermsBody": "Agar DPIP dapat memperingatkan Anda saat bencana terjadi, harap berikan izin berikut. Anda dapat mengubahnya kapan saja di pengaturan sistem.",
- "typhoonOverlaySectionWeather": "Weather underlay",
+ "typhoonOverlaySectionWeather": "Lapisan bawah cuaca",
"@meshtasticStateConnected": {
"description": "Connection state label"
},
"notifyOptWeatherLocal": "Hanya lokasi saat ini",
"mapNavRain": "Hujan",
- "moonDays": "days",
+ "moonDays": "hari",
"mapLegendUnit": "Satuan: {unit}",
"weatherModeClear": "Cerah",
"meshtasticRadio": "Radio",
"commonEmpty": "Tidak ada yang ditampilkan",
"mapLayerSatelliteB01": "Himawari Blue (B01)",
- "meshtasticExternalPower": "External power",
- "moonPhaseLastQuarter": "Last quarter",
+ "meshtasticExternalPower": "Daya eksternal",
+ "moonPhaseLastQuarter": "Kuartal akhir",
"@meshtasticName": {
"description": "The radio's long name"
},
@@ -551,20 +551,20 @@
"mapLayerRestroom": "Toilet Umum",
"restroomCategoryWelfare": "Lembaga kesejahteraan",
"restroomGradeExcellent": "Sangat baik",
- "meshtasticLastSent": "Last sent",
- "meshtasticName": "Name",
- "meshtasticScan": "Scan",
+ "meshtasticLastSent": "Terakhir dikirim",
+ "meshtasticName": "Nama",
+ "meshtasticScan": "Pindai",
"@radarOverlayMenuTooltip": {
"description": "Tooltip for the radar overlay-options chip beside the layer switcher"
},
"mapLayerCategoryForecast": "Prakiraan numerik",
- "meshtasticChannelFailed": "Couldn't set up the DPIP channel",
+ "meshtasticChannelFailed": "Gagal menyiapkan kanal DPIP",
"themeSystem": "Sistem",
"mapLayerSatelliteNdvi": "Himawari NDVI",
"typhoonLegendForecast": "Jalur prakiraan",
"typhoonValueHpa": "{n} hPa",
"weatherPrecipitation": "Curah hujan",
- "moonNextFullMoon": "Next full moon",
+ "moonNextFullMoon": "Purnama berikutnya",
"dpmSheetEmpty": "Ketuk penanda di peta untuk detail",
"onboardingSkipLeave": "Tetap lewati",
"aedPlaceDesc": "Lokasi peletakan",
@@ -582,22 +582,22 @@
},
"onboardingPermBattery": "Pengecualian baterai",
"typhoonLabelNw": "NW",
- "moonPhaseWaxingCrescent": "Waxing crescent",
+ "moonPhaseWaxingCrescent": "Bulan sabit membesar",
"restroomCategoryLeisure": "Tempat rekreasi",
"mapLayerTemperature": "Suhu",
"aedCategory": "Kategori",
"@moonTimelineCaption": {
"description": "Moon phase timeline caption"
},
- "meshtasticChannels": "Channels",
+ "meshtasticChannels": "Kanal",
"monitorWaiting": "Menunggu data…",
- "typhoonOverlayForecastCallouts": "Forecast tooltips",
+ "typhoonOverlayForecastCallouts": "Tooltip prakiraan",
"@meshtasticTitle": {
"description": "Meshtastic test page title"
},
"reportDetailEpicenter": "Koordinat episentrum",
- "meshtasticVoltage": "Voltage",
- "mapLayerMeshtasticSubtitle": "LoRa mesh nodes heard by your radio",
+ "meshtasticVoltage": "Tegangan",
+ "mapLayerMeshtasticSubtitle": "Node mesh LoRa yang terdengar radio Anda",
"@meshtasticSent": {
"description": "Packets sent this session"
},
@@ -623,34 +623,34 @@
"description": "Township-border overlay toggle in the map's radar overlay menu."
},
"mapLayerSatelliteB04": "Himawari Near-Infrared (B04)",
- "mapLayerSatelliteTransparentZero": "Zero difference = transparent (no signal)",
+ "mapLayerSatelliteTransparentZero": "Selisih nol = transparan (tanpa sinyal)",
"shelterIndoorLabel": "Penampungan dalam ruangan",
"notifyOptOff": "Nonaktif",
"reportFilterSortTime": "Waktu",
- "mapLayerSatelliteCloudProbablyClear": "Probably clear",
+ "mapLayerSatelliteCloudProbablyClear": "Mungkin cerah",
"weatherModeThunderstorm": "Badai petir",
"homeViewOnMap": "Lihat di peta",
"reportFilterIntensityInfoLegacyTitle": "Lama (sebelum 2020)",
- "typhoonLabelSpeed": "Past movement speed",
+ "typhoonLabelSpeed": "Kecepatan gerak",
"@meshtasticReconnecting": {
"description": "The link dropped and is being re-established"
},
"mapAppOpenFailed": "Tidak dapat membuka {app}",
- "mapLayerSatelliteRgbComposite": "RGB composite (JMA recipe)",
+ "mapLayerSatelliteRgbComposite": "Komposit RGB (resep JMA)",
"@meshtasticStateDisconnected": {
"description": "Connection state label"
},
- "meshtasticReceived": "Received",
+ "meshtasticReceived": "Diterima",
"weatherRankingExtremeLow": "Minimum hari ini",
"@meshtasticRegionSwitch": {
"description": "Button applying the DPIP LoRa region"
},
"mapLayerSatelliteB10": "Himawari Lower Water Vapour (B10)",
- "mapLayerSatelliteCloudProbablyCloudy": "Probably cloudy",
+ "mapLayerSatelliteCloudProbablyCloudy": "Mungkin berawan",
"shelterCategoryLabel": "Jenis bencana",
"mapLayerSatelliteTransparentNoWater": "≤ 0 = transparent (no water)",
- "meshtasticStateConnecting": "Connecting…",
- "moonTitle": "Moon",
+ "meshtasticStateConnecting": "Menghubungkan…",
+ "moonTitle": "Bulan",
"weatherRankingGust": "Hembusan",
"moreAppStore": "App Store",
"@meshtasticUndecoded": {
@@ -661,7 +661,7 @@
},
"moreServerStatus": "Status server",
"notifySectionWeather": "Cuaca",
- "meshtasticPreset": "Modem preset",
+ "meshtasticPreset": "Preset modem",
"dataSectionSeismic": "Seismik",
"changelogBodyEmpty": "Tidak ada catatan untuk rilis ini.",
"changelogOpenOnGitHub": "Lihat di GitHub",
@@ -670,15 +670,15 @@
"regionNationwide": "Seluruh negeri",
"moreNotifyLog": "Log notifikasi DPIP",
"regionCurrent": "Lokasi saat ini",
- "meshtasticNotConnected": "Not connected to a radio",
+ "meshtasticNotConnected": "Belum terhubung ke radio",
"weatherModeSnow": "Salju",
- "mapLayerMeshtastic": "Meshtastic nodes",
+ "mapLayerMeshtastic": "Node Meshtastic",
"moreDeveloper": "Info debug",
"@qpesumsOverlayMenuTooltip": {
"description": "Tooltip for the QPESUMS forecast overlay-options chip beside the layer switcher."
},
"mapLayerSatelliteB14": "Himawari Longwave Infrared (B14)",
- "meshtasticChannelUse": "Channel use",
+ "meshtasticChannelUse": "Penggunaan kanal",
"mapNavLightning": "Petir",
"homeForecastEmpty": "Tidak ada data prakiraan",
"sponsorOneTime": "Sekali bayar",
@@ -686,7 +686,7 @@
"onboardingPermBackground": "Lokasi latar belakang",
"aedEmergencyPhone": "Telepon darurat",
"dpmOpenInMaps": "Buka di peta",
- "meshtasticNotifyNodes": "Notify on new nodes",
+ "meshtasticNotifyNodes": "Beri tahu saat node baru",
"onboardingPermCriticalDesc": "Memungkinkan peringatan gempa yang mengancam jiwa tetap berbunyi bahkan dalam mode senyap atau Jangan Ganggu.",
"@mapAppDefault": {
"placeholders": {
@@ -695,11 +695,11 @@
}
}
},
- "mapLayerSatelliteTransparentWarm": "Clear sky (warm end) = transparent, the basemap shows",
- "meshtasticSent": "Sent",
+ "mapLayerSatelliteTransparentWarm": "Langit cerah (ujung hangat) = transparan, peta dasar terlihat",
+ "meshtasticSent": "Terkirim",
"homeForecastTitle": "Prakiraan 24 jam",
"typhoonLegendWarningAreas": "Area peringatan",
- "meshtasticExcludeMqttHidden": "{count} hidden",
+ "meshtasticExcludeMqttHidden": "{count} disembunyikan",
"notifyOptLocalIntensity1": "Intensitas lokal 1 atau lebih",
"@skyTimeGolden": {
"description": "Label for the skyTimeGolden option in the experimental backdrop settings."
@@ -710,21 +710,21 @@
"mapTimelinePast": "Lampau",
"restroomTypeFemale": "Toilet wanita",
"reportListToday": "Hari ini",
- "meshtasticTapNode": "Tap a node for details",
+ "meshtasticTapNode": "Ketuk node untuk detail",
"commonLoading": "Memuat…",
"@meshtasticStateConnecting": {
"description": "Connection state label"
},
- "typhoonIntensityModerate": "Moderate typhoon",
+ "typhoonIntensityModerate": "Topan sedang",
"mapLayerSatelliteAsh": "Himawari Ash",
"rainInterval3h": "3 jam",
- "meshtasticChannelReady": "DPIP channel ready",
+ "meshtasticChannelReady": "Kanal DPIP siap",
"@meshtasticNotifyNodes": {
"description": "Toggle: local notification when a new node is heard"
},
"mapLayerCategorySatellite": "Satelit",
"mapLayerSatelliteNightmicrophysics": "Himawari Night Microphysics",
- "typhoonIntensityTd": "Tropical depression",
+ "typhoonIntensityTd": "Depresi tropis",
"reportFilterDate": "Tanggal",
"sponsorRestoreUnavailable": "Tidak dapat terhubung ke toko. Coba lagi nanti.",
"homeForecastPop": "{pop}%",
@@ -773,13 +773,13 @@
}
},
"mapLayerSatelliteBtdSo2": "Himawari SO₂ / Cloud Phase",
- "meshtasticStateError": "Error",
+ "meshtasticStateError": "Kesalahan",
"weatherModeOvercast": "Mendung",
"@meshtasticScan": {
"description": "Start scanning for Meshtastic radios"
},
"reportDetailDepth": "Kedalaman hiposenter",
- "typhoonOverlayWarningTooltip": "Highlight counties under a typhoon warning",
+ "typhoonOverlayWarningTooltip": "Sorot kabupaten dalam peringatan topan",
"reportFilterDatePick": "Pilih tanggal",
"onboardingSkipStay": "Kembali",
"@moonPhaseWaxingCrescent": {
@@ -793,16 +793,16 @@
"description": "Transmit power"
},
"shelterOutdoorLabel": "Penampungan luar ruangan",
- "meshtasticStateConnected": "Connected",
+ "meshtasticStateConnected": "Terhubung",
"mapNavRadar": "Radar",
"mapLayerSatelliteCloudClear": "Clear",
"eewSummary": "M{magnitude} · kedalaman {depth} km",
"locationBannerPermission": "Izin lokasi mati — peringatan lokal tidak dapat menargetkan wilayah Anda.",
- "typhoonOverlayWeatherNoneTooltip": "No radar or infrared underlay",
+ "typhoonOverlayWeatherNoneTooltip": "Tanpa lapisan bawah radar atau inframerah",
"radarCountyOutlineHint": "Digambar di atas gema",
"windForecastCountyOutlineHint": "Digambar di atas bidang angin",
"homeRainTrendTitle": "Hujan 1 jam ke depan",
- "moonPhaseFirstQuarter": "First quarter",
+ "moonPhaseFirstQuarter": "Kuartal pertama",
"mapLayerCategoryTyphoon": "Topan",
"@windForecastOverlayMenuTooltip": {
"description": "Tooltip for the wind-forecast overlay-options chip beside the layer switcher."
@@ -810,13 +810,13 @@
"@meshtasticNodeId": {
"description": "The radio's node number"
},
- "meshtasticUtilization": "Airtime (24h)",
+ "meshtasticUtilization": "Waktu udara (24 jam)",
"restroomTypeMixed": "Toilet campuran",
"restroomGradeGood": "Baik",
"notifyTsunami": "Informasi tsunami",
"navData": "Data",
"mapLayerSatelliteBtdWvirw": "Himawari Overshooting Top",
- "meshtasticReadingAge": "Reading taken",
+ "meshtasticReadingAge": "Waktu pengukuran",
"@moonPhaseWaningGibbous": {
"description": "Phase: waning gibbous"
},
@@ -829,7 +829,7 @@
"notifyIntensity": "Laporan intensitas",
"rainIntervalMenu": "Jendela akumulasi",
"reportDetailLocalFelt": "Gempa Dirasakan Lokal",
- "meshtasticDevice": "Device",
+ "meshtasticDevice": "Perangkat",
"onboardingGrant": "Berikan",
"weatherModeRain": "Hujan",
"shelterVulnerableOkLabel": "Ramah kelompok rentan",
@@ -853,7 +853,7 @@
"trendCumulativeTotal": "Total {total} mm",
"languageName": "Bahasa Indonesia",
"reportListEmptyFiltered": "Tidak ada laporan yang cocok dengan filter",
- "meshtasticExcludeMqtt": "Hide MQTT nodes",
+ "meshtasticExcludeMqtt": "Sembunyikan node MQTT",
"mapNavTyphoon": "Topan",
"weatherModeSand": "Debu",
"@moonPhaseFirstQuarter": {
@@ -869,9 +869,9 @@
"feedStale": "Data mungkin sudah usang",
"homeForecastWind": "{direction} · Skala {level}",
"navHome": "Beranda",
- "meshtasticRegionLabel": "Region",
+ "meshtasticRegionLabel": "Wilayah",
"mapLayerSatelliteCloudtop": "Himawari Cloud Top Temperature",
- "moonTimelineCaption": "Phase",
+ "moonTimelineCaption": "Fase",
"@meshtasticChannelNoSlot": {
"description": "Every secondary channel slot is taken"
},
@@ -886,7 +886,7 @@
"reportFilterSortDepth": "Kedalaman",
"mapTimelineDataTime": "Waktu data {time}",
"radarScanRange": "Tampilkan jangkauan pindai",
- "meshtasticHopLimit": "Hop limit",
+ "meshtasticHopLimit": "Batas lompatan",
"@meshtasticUptime": {
"description": "Time since the radio booted"
},
@@ -897,17 +897,17 @@
"sponsorPrivacy": "Kebijakan Privasi",
"reportDetailLocalIntensity": "Intensitas di lokasi Anda",
"mapLayerSatelliteNaturalcolor": "Himawari Natural Color",
- "meshtasticAirtime": "Air time (TX)",
+ "meshtasticAirtime": "Waktu udara (TX)",
"shelterCapacityValue": "{n} orang",
"lightningLegendCc": "Awan–awan · {minutes} mnt",
- "meshtasticSendHint": "Message to broadcast",
+ "meshtasticSendHint": "Pesan untuk disiarkan",
"monitorDelay": "Latensi {value} s",
"@meshtasticFirmware": {
"description": "Firmware version"
},
"dpmNo": "Tidak",
"mapLayerSatelliteB08": "Himawari Upper Water Vapour (B08)",
- "meshtasticReconnecting": "Reconnecting…",
+ "meshtasticReconnecting": "Menghubungkan ulang…",
"@mapAppAppleMaps": {},
"@meshtasticReadingAge": {
"description": "How old the battery/airtime numbers are"
@@ -916,16 +916,16 @@
"@moonPhaseWaxingGibbous": {
"description": "Phase: waxing gibbous"
},
- "typhoonOverlayWeatherSatelliteTooltip": "Infrared closest to the typhoon bulletin time",
+ "typhoonOverlayWeatherSatelliteTooltip": "Inframerah terdekat dengan waktu buletin topan",
"radarScanRangeHint": "Di luar kotak berarti tak terpantau",
- "typhoonPickerTd": "Tropical depression TD {no}",
+ "typhoonPickerTd": "Depresi tropis TD {no}",
"mapLayerSatelliteWatervapor": "Himawari Water Vapour",
"regionAddButton": "Tambah wilayah",
"displaySettings": "Tampilan",
"restroomGradePoor": "Di bawah standar",
"restroomCategoryTourist": "Kawasan wisata",
"locationBannerServiceOff": "Layanan lokasi mati — peringatan lokal tidak dapat menargetkan wilayah Anda.",
- "mapLayerStyleTooltip": "Colour style",
+ "mapLayerStyleTooltip": "Gaya warna",
"lightningLegendCg": "Awan–tanah · {minutes} mnt",
"skyTimeAuto": "Otomatis",
"appLogs": "Log aplikasi",
@@ -970,13 +970,13 @@
"endpointServiceSatellite": "Satellite",
"endpointServiceQpesums": "QPE",
"endpointServiceWind": "Wind",
- "endpointServiceDpm": "Disaster points",
+ "endpointServiceDpm": "Titik bencana",
"endpointServiceWeather": "Weather",
"endpointServiceRain": "Rain",
"endpointServiceLightning": "Lightning",
"endpointServiceTyphoon": "Typhoon",
"endpointServiceReport": "EQ reports",
- "endpointServiceTremStation": "Tremor station",
+ "endpointServiceTremStation": "Stasiun getaran",
"endpointServiceEvent": "Events",
"endpointServiceLocation": "Location",
"endpointServiceNotify": "Notifications",
@@ -989,16 +989,16 @@
"weatherHumidity": "Kelembapan",
"typhoonValueMs": "{n} m/s",
"homeForecastHumidity": "Kelembapan {value}%",
- "meshtasticBusyBody": "Disconnect it in the other Meshtastic app first. Two apps on one radio take each other's messages, so some will go missing.",
- "meshtasticChannelNoSlot": "No free channel slot — free one on the radio",
+ "meshtasticBusyBody": "Putuskan koneksinya dulu di aplikasi Meshtastic lain. Dua aplikasi pada satu radio saling mengambil pesan, jadi sebagian akan hilang.",
+ "meshtasticChannelNoSlot": "Tidak ada slot kanal kosong — kosongkan satu di radio",
"restroomCategoryTransport": "Transportasi",
- "meshtasticBattery": "Battery",
+ "meshtasticBattery": "Baterai",
"meshtasticDistance": "Jarak",
"meshtasticSnrTrend": "Tren sinyal (SNR)",
"meshtasticBatteryTrend": "Tren baterai",
- "typhoonOverlayMenuTooltip": "Typhoon overlay options",
+ "typhoonOverlayMenuTooltip": "Opsi lapisan topan",
"mapLayerSatelliteBtdOzone": "Himawari Tropopause",
- "meshtasticRegionMismatch": "Radio region is {region} — DPIP needs TW",
+ "meshtasticRegionMismatch": "Wilayah radio adalah {region} — DPIP membutuhkan TW",
"notifySectionEarthquake": "Gempa bumi",
"mapLayerDisasterMap": "Peta Bencana",
"weatherModeFog": "Kabut",
@@ -1007,9 +1007,10 @@
"moreAnnouncements": "Pengumuman",
"moreTagline": "Platform Integrasi Informasi Bencana",
"moreVersionStable": "Versi resmi",
- "moreVersionNotes": "Versi saat ini",
+ "moreVersionNotes": "Pembaruan ini",
+ "moreVersionNotesHighlightsSubtitle": "Apa yang berubah di versi ini",
"releaseHighlightsSeeNotes": "Catatan rilis lengkap",
- "releaseHighlightsTitle": "Yang berubah",
+ "releaseHighlightsTitle": "{train} rangkuman",
"releaseHighlightsTabNormal": "Untuk pengguna",
"releaseHighlightsTabAdvanced": "Mendalam",
"releaseHighlightsEmpty": "Belum ada konten.",
@@ -1028,7 +1029,7 @@
"typhoonOverlayWeatherNone": "None",
"mapLayerStyleGray": "Grayscale (JMA)",
"weatherModeAuto": "Otomatis",
- "typhoonLabelProbCircle": "70% probability circle",
+ "typhoonLabelProbCircle": "Lingkaran probabilitas 70%",
"@radarCountyOutline": {
"description": "County-border overlay toggle in the map's radar overlay menu."
},
@@ -1038,27 +1039,27 @@
"@skyTimeSunrise": {
"description": "Label for the skyTimeSunrise option in the experimental backdrop settings."
},
- "typhoonLabelDirection": "Past movement direction",
+ "typhoonLabelDirection": "Arah gerak",
"@meshtasticLastSent": {
"description": "Age of the last sent packet"
},
"regionManageTitle": "Wilayah tersimpan",
- "regionSaveNote": "Notifikasi dikirim berdasarkan lokasi GPS Anda. Menyimpan wilayah sering dipakai tidak mengubah tempat pengiriman peringatan — wilayah sering dipakai hanya agar status tiap wilayah terlihat cepat di beranda. Izinkan akses lokasi, jika tidak notifikasi tidak berfungsi.",
+ "regionSaveNote": "Notifikasi dikirim berdasarkan lokasi GPS Anda. Menyimpan wilayah sering dipakai tidak mengubah tempat pengiriman peringatan — wilayah sering dipakai hanya agar status tiap wilayah terlihat cepat di beranda. Izinkan akses lokasi, jika tidak notifikasi tidak berfunosm.",
"@regionSaveNote": {
"description": "Penjelasan tentang mekanisme notifikasi dan wilayah sering dipakai"
},
"typhoonLegendCone": "Kerucut prakiraan",
"moreCwaEew": "Peringatan dini gempa CWA",
"onboardingPermsTitle": "Izin",
- "mapLayerStyleJma": "Cloud-top enhancement (JMA)",
+ "mapLayerStyleJma": "Peningkatan puncak awan (JMA)",
"rainInterval10m": "10 mnt",
- "meshtasticConnectAnyway": "Connect anyway",
+ "meshtasticConnectAnyway": "Tetap hubungkan",
"reportListDayCount": "{count}",
"mapLayerSatelliteB06": "Himawari Near-Infrared (B06)",
- "mapLayerSatelliteTransparentReflectance": "Low reflectance / night = transparent, the basemap shows",
+ "mapLayerSatelliteTransparentReflectance": "Reflektansi rendah / malam = transparan, peta dasar terlihat",
"chartHourLabel": "{hour}j",
"mapLayerShelter": "Tempat Evakuasi",
- "typhoonOverlayProbabilityTooltip": "Show strike probability (hides the forecast cone)",
+ "typhoonOverlayProbabilityTooltip": "Tampilkan probabilitas hantaman (menyembunyikan kerucut prakiraan)",
"mapLayerSatelliteNdwi": "Himawari NDWI",
"disasterMapOverlayShelterTooltip": "Tampilkan tempat evakuasi",
"mapNavHumidity": "Kelembapan",
@@ -1068,7 +1069,7 @@
"reportDetailSortByIntensity": "Urutkan menurut intensitas",
"homeRainTrendNoData": "Tidak ada data",
"mapLayerCategoryRadar": "Radar",
- "meshtasticShortName": "Short name",
+ "meshtasticShortName": "Nama pendek",
"@meshtasticStateConfiguring": {
"description": "Connection state label"
},
@@ -1088,7 +1089,7 @@
"@skyTimeMorning": {
"description": "Label for the skyTimeMorning option in the experimental backdrop settings."
},
- "meshtasticRegionConfirm": "Switch this radio to the TW region? It restarts and disconnects for a moment, and every other channel on it moves too.",
+ "meshtasticRegionConfirm": "Beralihkan radio ini ke wilayah TW? Radio akan mulai ulang dan terputus sesaat, dan semua kanal lain ikut pindah.",
"dataEarthquakeSubtitle": "Laporan gempa",
"typhoonNoActive": "Tidak ada topan aktif",
"@meshtasticExcludeMqttHidden": {
@@ -1105,10 +1106,55 @@
"@meshtasticChannels": {
"description": "Section: the radio's channel table"
},
+ "mapOsmOverlay": "Peta detail",
+ "mapOsmOverlayHint": "Tampilkan jalan, bangunan, dan nama tempat yang lebih lengkap",
+ "mapOsmDetails": "Detail lapisan",
+ "moreDataSources": "Sumber data",
+ "dataSourceTremNet": "探索智慧科技有限公司 — TREM-Net",
+ "dataSourceCwa": "交通部中央氣象署 (CWA)",
+ "dataSourceJma": "気象庁 (JMA)",
+ "dataSourceNcdr": "國家災害防救科技中心 (NCDR)",
+ "dataSourceEcmwf": "European Centre for Medium-Range Weather Forecasts (ECMWF)",
+ "dataSourceNoaaGfs": "National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)",
+ "dataSourceGovernmentOpenData": "政府資料開放平臺",
+ "dataSourceOpenStreetMap": "© OpenStreetMap contributors",
+ "dataSourceNasaMoon": "National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)",
+ "mapOsmDetailsHint": "{enabled} dari {total} lapisan aktif",
+ "@mapOsmDetailsHint": {
+ "description": "How many of the OSM layers are enabled",
+ "placeholders": {
+ "enabled": {
+ "type": "int"
+ },
+ "total": {
+ "type": "int"
+ }
+ }
+ },
+ "mapOsmSurface": "Permukaan",
+ "mapOsmParks": "Taman",
+ "mapOsmLandUse": "Penggunaan lahan",
+ "mapOsmAirportAreas": "Area bandara",
+ "mapOsmWater": "Perairan",
+ "mapOsmRivers": "Sungai",
+ "mapOsmBoundaries": "Batas",
+ "mapOsmBuildings": "Bangunan",
+ "mapOsmRoads": "Jalan",
+ "mapOsmRoadNames": "Nama jalan",
+ "mapOsmWaterNames": "Nama perairan",
+ "mapOsmPeaks": "Puncak",
+ "mapOsmAirportNames": "Nama bandara",
+ "mapOsmPlaceNames": "Nama tempat",
+ "mapOsmPoi": "Tempat menarik",
+ "mapOsmHouseNumbers": "Nomor rumah",
+ "mapOsmRestoreAll": "Pulihkan semua",
+ "mapOsmSectionNatural": "Fitur alam",
+ "mapOsmSectionRoadsAndBuildings": "Jalan & bangunan",
+ "mapOsmSectionLabelsAndPlaces": "Label & tempat",
"mapTownLabels": "Nama kecamatan",
"notifySetFailed": "Tidak dapat menyimpan pengaturan. Silakan coba lagi.",
- "meshtasticDisconnect": "Disconnect",
- "meshtasticUndecoded": "Not decrypted",
+ "meshtasticDisconnect": "Putuskan",
+ "meshtasticUndecoded": "Belum didekripsi",
"notifyAnnouncement": "Pengumuman",
"onboardingIntroTitle": "Selamat datang di DPIP",
"regionCurrentUnavailable": "Tidak dapat memperoleh lokasi saat ini",
@@ -1230,7 +1276,7 @@
"@sunGoldenHourEvening": {
"description": "Evening golden hour span"
},
- "sunBlueHour": "Blue hour",
+ "sunBlueHour": "Jam biru",
"@sunBlueHour": {
"description": "Blue hour span after sunset"
},
@@ -1799,6 +1845,30 @@
"description": "Button that opens the system settings page"
},
"permissionSettingsMessage": "“{what}” ditolak dan sistem tidak akan bertanya lagi. Aktifkan di Pengaturan.",
+ "permissionGuideNotification": "Buka Pengaturan Sistem untuk mengizinkan notifikasi.",
+ "permissionGuideForegroundLocation": "Buka Pengaturan Sistem untuk mengizinkan lokasi presisi.",
+ "permissionGuideBackgroundLocation": "Di “{option}”, pilih “Izinkan sepanjang waktu”.",
+ "@permissionGuideBackgroundLocation": {
+ "description": "Instruction for background location",
+ "placeholders": {
+ "option": {}
+ }
+ },
+ "permissionGuideBackgroundExecution": "Izinkan eksekusi latar belakang di Pengaturan Sistem agar notifikasi tidak dijeda.",
+ "permissionGuideUnusedPause": "Jika aplikasi ditandai “tidak digunakan”, pilih “Izinkan” di Pengaturan Sistem.",
+ "permissionGuideUnusedFreeSpace": "Jika aplikasi dijeda karena penyimpanan, bersihkan cache dan buka kembali.",
+ "permissionGuideUnusedRevoke": "Jika izin aplikasi dicabut, berikan lagi di Pengaturan Sistem.",
+ "permissionGuideUnusedPlayProtect": "Jika Play Protect menjeda aplikasi, periksa statusnya di Google Play.",
+ "permissionGuideVendorPower": "Di pengaturan hemat daya “{vendor}”, atur aplikasi ini ke “Tanpa batas”.",
+ "@permissionGuideVendorPower": {
+ "description": "Instruction for vendor power saving",
+ "placeholders": {
+ "vendor": {}
+ }
+ },
+ "permissionStillRequired": "Masih diperlukan — buka Pengaturan untuk mengaktifkannya.",
+ "permissionVerifyManually": "Periksa secara manual bahwa izin ini diaktifkan di Pengaturan Sistem.",
+ "permissionBackgroundLocationOption": "“Izinkan sepanjang waktu”",
"@permissionSettingsMessage": {
"description": "Explains that the system will not ask again for this permission",
"placeholders": {
@@ -1872,6 +1942,9 @@
},
"moreDumpDiagnostics": "Unggah info debug dan log",
"moreDumpDiagnosticsHint": "Mengunggah lalu menyalin tautan untuk dilampirkan ke laporan",
+ "dumpIncludeSensitive": "Sertakan lokasi presisi",
+ "dumpIncludeSensitiveHint": "Menyertakan koordinat dari log dan lokasi latar belakang; jika tidak dipilih, diganti dengan null",
+ "dumpUpload": "Unggah",
"dumpUploaded": "Terunggah",
"dumpLinkCopied": "Tautan disalin ke papan klip",
"dumpCopyAgain": "Salin lagi",
diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb
index 60c77ab49..7101eaaaf 100644
--- a/lib/l10n/app_ja.arb
+++ b/lib/l10n/app_ja.arb
@@ -19,29 +19,29 @@
"reportFilterIntensity": "震度",
"mapLayerLightning": "雷",
"restroomTypeMale": "男性用トイレ",
- "meshtasticLastReceived": "Last received",
+ "meshtasticLastReceived": "最終受信",
"reportDetailSortByCounty": "地域順に並べ替え",
"@moonDays": {
"description": "Day unit for the moon age"
},
"homeRainTrendScattered": "にわか雨の可能性があります",
- "meshtasticUptime": "Uptime",
+ "meshtasticUptime": "稼働時間",
"weatherRankingTempExtremes": "気温極値",
"themeLight": "ライト",
"mapTerrainReliefHint": "ベースマップに地形の陰影を表示",
- "meshtasticEmptyMessage": "(empty message)",
+ "meshtasticEmptyMessage": "(空メッセージ)",
"moreSectionRegion": "地域",
"mapLayerSatellite": "ひまわり 赤外線(B13)",
"@meshtasticTapNode": {
"description": "Resting state of the map node sheet"
},
"aedHoursSaturday": "土曜の開館時間",
- "moonPhaseNew": "New moon",
+ "moonPhaseNew": "新月",
"notifySectionEew": "緊急地震速報",
"mapResetNorth": "北を上にする",
"rainInterval2d": "2日",
"mapTownLabelsHint": "拡大すると郷鎮名を表示",
- "commonCancel": "Cancel",
+ "commonCancel": "キャンセル",
"notifyOptTsunamiWarning": "津波警報のみ",
"mapLayerSatelliteBtdFog": "ひまわり 夜間霧",
"@meshtasticSelectDevice": {
@@ -82,15 +82,15 @@
"changelogShowSnapshots": "スナップショットを表示",
"changelogTitle": "更新履歴",
"reportFilterOrderDesc": "降順",
- "meshtasticExcludeMqttSubtitle": "Nodes bridged over the internet, not heard by radio",
+ "meshtasticExcludeMqttSubtitle": "インターネット経由で橋渡しされたノード(無線では受信していません)",
"reportFilterIntensityInfoTitle": "震度の新制と旧制",
"mapLayerTyphoon": "台風",
"radarOverlayMenuTooltip": "レーダーレイヤー設定",
"@meshtasticChannelUse": {
"description": "Share of airtime seen busy"
},
- "meshtasticNodes": "Nodes",
- "meshtasticSend": "Send",
+ "meshtasticNodes": "ノード",
+ "meshtasticSend": "送信",
"typhoonOverlayStormL7Tooltip": "強風域 + 平均円(紫)",
"aedType": "種類",
"termsOfService": "利用規約",
@@ -110,12 +110,12 @@
"@meshtasticExcludeMqttSubtitle": {
"description": "What an MQTT node is"
},
- "meshtasticFirmware": "Firmware",
+ "meshtasticFirmware": "ファームウェア",
"@mapLayerMeshtastic": {
"description": "Map layer name: mesh nodes"
},
"reportFilterDateEndNote": "終了日:当日 24:00(台北時間)",
- "meshtasticSilent": "Silent",
+ "meshtasticSilent": "サイレント",
"reportFilterSortMagnitude": "規模",
"mapLayerCategoryEarthquake": "地震",
"mapLayerSatelliteB12": "ひまわり オゾン(B12)",
@@ -144,9 +144,9 @@
"@radarCountyOutlineHint": {
"description": "Hint under the county-border toggle in the radar overlay menu."
},
- "meshtasticLayerOptions": "Node options",
+ "meshtasticLayerOptions": "ノードオプション",
"onboardingAgreeContinue": "同意して続行",
- "meshtasticNodeId": "Node ID",
+ "meshtasticNodeId": "ノード ID",
"commonRetry": "再試行",
"reportDetailNumbered": "No.{number} 顕著有感地震",
"typhoonOverlayStormBandSubtitle": "平均円付き",
@@ -161,12 +161,12 @@
"@meshtasticSilent": {
"description": "Legend: node known but not heard recently"
},
- "meshtasticChannelWorking": "Setting up the DPIP channel…",
- "meshtasticRegionSwitch": "Switch to TW",
+ "meshtasticChannelWorking": "DPIP チャンネルを設定中…",
+ "meshtasticRegionSwitch": "TW 地域に切り替え",
"@meshtasticLastReceived": {
"description": "Age of the last received packet"
},
- "meshtasticTraffic": "Traffic",
+ "meshtasticTraffic": "トラフィック",
"@meshtasticDpipChannel": {
"description": "Which channel DPIP payloads use"
},
@@ -177,7 +177,7 @@
},
"mapLayerHumidity": "湿度",
"mapLayerSatelliteTransparentNight": "夜間 = 透明、地図が透ける",
- "meshtasticScanning": "Scanning…",
+ "meshtasticScanning": "スキャン中…",
"@meshtasticDevice": {
"description": "Section: device identity"
},
@@ -202,7 +202,7 @@
"meshtasticEtaDays": "約{n}日",
"meshtasticTitle": "Meshtastic",
"navMore": "その他",
- "meshtasticDpipChannel": "DPIP channel",
+ "meshtasticDpipChannel": "DPIP チャンネル",
"disasterMapOverlaySectionLayers": "レイヤー",
"@moonPhaseWaningCrescent": {
"description": "Phase: waning crescent"
@@ -215,13 +215,13 @@
"description": "Label for the weatherModeCloudy option in the experimental backdrop settings."
},
"typhoonLabelNe": "北東",
- "meshtasticCopied": "Message copied",
+ "meshtasticCopied": "メッセージをコピーしました",
"reportListEmpty": "地震報告はありません",
"reportListEnd": "これ以上ありません",
"mapLayerSatelliteTruecolor": "ひまわり トゥルーカラー",
"typhoonOverlaySectionExtra": "オーバーレイ",
"eewSWave": "S波",
- "meshtasticBusyTitle": "Another app is using this radio",
+ "meshtasticBusyTitle": "別のアプリがこの無線機を使用中です",
"restroomCategoryCultural": "文化・娯楽施設",
"typhoonLabelWind": "中心付近の最大風速",
"radarGlobalOutlineHint": "各国の国境外枠",
@@ -233,11 +233,11 @@
"@meshtasticRadioSettings": {
"description": "Section: LoRa settings"
},
- "dataSectionAstronomy": "Astronomy",
+ "dataSectionAstronomy": "天文",
"homeRainTrendLightSustained": "今後1時間は小雨が続きます",
"commonError": "問題が発生しました",
- "moonPhaseWaningCrescent": "Waning crescent",
- "meshtasticPower": "Power",
+ "moonPhaseWaningCrescent": "下弦の月",
+ "meshtasticPower": "電源",
"@meshtasticChannelWorking": {
"description": "Creating/verifying the DPIP channel"
},
@@ -248,7 +248,7 @@
"typhoonWarningAreas": "対象地域:{areas}",
"rainIntervalSection": "集計時間",
"notifyTitle": "通知",
- "meshtasticTxPower": "TX power",
+ "meshtasticTxPower": "TX 出力",
"@radarTownOutlineHint": {
"description": "Hint under the township-border toggle in the radar overlay menu."
},
@@ -307,14 +307,14 @@
"description": "Radar scan-range overlay toggle in the map's radar overlay menu."
},
"restroomCategoryReligious": "宗教・礼拝施設",
- "meshtasticRole": "Role",
+ "meshtasticRole": "ロール",
"mapLayerSatelliteCloudCloudy": "雲",
"skyTimeSunrise": "日の出",
"@mapLayerMeshtasticSubtitle": {
"description": "Map layer switcher subtitle"
},
"meshtasticJumpToLatest": "最新へ移動",
- "meshtasticNoMessages": "No messages yet",
+ "meshtasticNoMessages": "まだメッセージがありません",
"onboardingPermNotifyDesc": "地震、天気、災害の発生時に、警報をすぐお届けします。",
"radarTownOutline": "市町村境界",
"mapLayerStyleSection": "色調",
@@ -323,7 +323,7 @@
},
"disasterMapOverlayMenuTooltip": "防災マップのレイヤー",
"moreGooglePlay": "Google Play",
- "meshtasticOnline": "Heard recently",
+ "meshtasticOnline": "最近受信あり",
"@meshtasticSendHint": {
"description": "Message input hint"
},
@@ -350,10 +350,10 @@
"mapLayerSatelliteTransparentNoVegetation": "< 0.1 = 透明(植生なし)",
"notifyOptLocalIntensity4": "所在地の震度4以上",
"eewArrived": "到達",
- "meshtasticNoDevices": "No Meshtastic devices found",
+ "meshtasticNoDevices": "Meshtastic デバイスが見つかりません",
"mapLayerCategoryLife": "生活",
"reportFilterSortIntensity": "震度",
- "meshtasticStateDisconnected": "Disconnected",
+ "meshtasticStateDisconnected": "切断済み",
"typhoonIntensityIntense": "強い台風",
"@meshtasticSend": {
"description": "Send message button"
@@ -366,7 +366,7 @@
"description": "The radio's short name"
},
"dpmYes": "はい",
- "meshtasticNoHistory": "Not enough history yet",
+ "meshtasticNoHistory": "履歴がまだ足りません",
"reportDetailLocalIntensityUnavailable": "震度情報なし",
"mapLayerWindForecastGfs": "GFS",
"reportFilterDepth": "深さ",
@@ -391,7 +391,7 @@
"reportFilterReset": "リセット",
"mapLayerSatelliteMndwi": "ひまわり MNDWI",
"typhoonOverlaySectionStorm": "暴風域",
- "moonPhaseFull": "Full moon",
+ "moonPhaseFull": "満月",
"@meshtasticEmptyMessage": {
"description": "Placeholder for a text packet with no body"
},
@@ -399,24 +399,24 @@
"@radarGlobalOutlineHint": {
"description": "Hint under the national-border toggle in the radar overlay menu."
},
- "moonPhaseWaningGibbous": "Waning gibbous",
+ "moonPhaseWaningGibbous": "下弦の月(虧)",
"reportFilterIntensityInfoModernTitle": "新制(2020 年以降)",
"@mapAppGoogleMaps": {},
"typhoonDataTime": "資料時刻\n{time}",
"restroomTypeAccessible": "バリアフリートイレ",
"moreSectionAbout": "情報",
- "meshtasticSelectDevice": "Select a radio",
+ "meshtasticSelectDevice": "無線機を選択",
"onboardingIntroBody": "DPIP はあなたと共にある防災パートナーです。緊急地震速報、地震報告、天気、各種災害情報を統合し、重要な瞬間にすぐお知らせします。\n\n• 地震:緊急地震速報、震度速報、地震報告\n• 天気:雷雨即時情報、気象警報・注意報\n• 津波・防災情報\n\n次に、サービス利用規約をご確認いただき、DPIP がリアルタイムであなたを守れるよう、いくつかの権限の許可をお願いします。",
"shelterCapacityLabel": "収容人数",
"reportDetailImage": "地震レポート画像",
- "meshtasticStateConfiguring": "Configuring…",
+ "meshtasticStateConfiguring": "設定中…",
"@moonPhaseLastQuarter": {
"description": "Phase: last quarter"
},
"typhoonLabelGaleAvg": "強風域の平均半径",
"onboardingPermNotify": "通知",
- "meshtasticClearMessages": "Clear messages",
- "meshtasticNotifyMessages": "Notify on new messages",
+ "meshtasticClearMessages": "メッセージを消去",
+ "meshtasticNotifyMessages": "新しいメッセージで通知",
"defaultMapLayerSettings": "地図の初期レイヤー",
"eewSourceSettings": "緊急地震速報の情報源",
"eewSourceSubtitle": "表示する緊急地震速報の発表機関を選択します。",
@@ -463,7 +463,7 @@
},
"notifyThunderstorm": "雷雨情報",
"skyTimeGolden": "ゴールデンアワー",
- "moonAge": "Age",
+ "moonAge": "月齢",
"@windForecastTownOutlineHint": {
"description": "Hint under the township-border toggle in the wind-forecast overlay menu."
},
@@ -474,7 +474,7 @@
"moreGithub": "ExpTech GitHub",
"homeForecastUnavailable": "地域を選ぶと予報を表示します",
"mapLayers": "レイヤー",
- "meshtasticHardware": "Hardware",
+ "meshtasticHardware": "ハードウェア",
"languageSettings": "言語設定",
"@moonNextFullMoon": {
"description": "Next full moon date label"
@@ -487,7 +487,7 @@
},
"skyTimeDawn": "夜明け前",
"skyTimeAfternoon": "午後",
- "meshtasticLastHeard": "Last heard",
+ "meshtasticLastHeard": "最終受信",
"typhoonWarningTitle": "台風警報",
"moreSourceCode": "ソースコード",
"mapLayerCategoryWeather": "気象観測",
@@ -507,12 +507,12 @@
"restroomTypeLabel": "種別",
"navEarthquake": "地震",
"typhoonOverlayStormL10Tooltip": "暴風域 + 平均円(黄)",
- "moonPhaseWaxingGibbous": "Waxing gibbous",
+ "moonPhaseWaxingGibbous": "上弦の月(盈)",
"reportDetailTitle": "地震レポート",
"moreTremReport": "TREM 検知レポート",
"weatherDataTime": "{station} · データ時刻 {time}",
- "meshtasticNoNodes": "No nodes heard yet",
- "meshtasticViaMqtt": "Via MQTT (internet)",
+ "meshtasticNoNodes": "まだノードを検出していません",
+ "meshtasticViaMqtt": "MQTT 経由(インターネット)",
"radarCountyOutline": "県市境界",
"@mapAppCopyCoordinates": {},
"commonClose": "閉じる",
@@ -529,14 +529,14 @@
},
"notifyOptWeatherLocal": "現在地のみ",
"mapNavRain": "雨量",
- "moonDays": "days",
+ "moonDays": "日",
"mapLegendUnit": "単位:{unit}",
"weatherModeClear": "晴れ",
- "meshtasticRadio": "Radio",
+ "meshtasticRadio": "無線機",
"commonEmpty": "表示する項目がありません",
"mapLayerSatelliteB01": "ひまわり 可視青(B01)",
- "meshtasticExternalPower": "External power",
- "moonPhaseLastQuarter": "Last quarter",
+ "meshtasticExternalPower": "外部電源",
+ "moonPhaseLastQuarter": "下弦",
"@meshtasticName": {
"description": "The radio's long name"
},
@@ -551,20 +551,20 @@
"mapLayerRestroom": "トイレ",
"restroomCategoryWelfare": "社会福祉施設・集会所",
"restroomGradeExcellent": "最上級",
- "meshtasticLastSent": "Last sent",
- "meshtasticName": "Name",
- "meshtasticScan": "Scan",
+ "meshtasticLastSent": "最終送信",
+ "meshtasticName": "名前",
+ "meshtasticScan": "スキャン",
"@radarOverlayMenuTooltip": {
"description": "Tooltip for the radar overlay-options chip beside the layer switcher"
},
"mapLayerCategoryForecast": "数値予報",
- "meshtasticChannelFailed": "Couldn't set up the DPIP channel",
+ "meshtasticChannelFailed": "DPIP チャンネルの設定に失敗しました",
"themeSystem": "システム",
"mapLayerSatelliteNdvi": "ひまわり NDVI",
"typhoonLegendForecast": "予報経路",
"typhoonValueHpa": "{n} hPa",
"weatherPrecipitation": "降水量",
- "moonNextFullMoon": "Next full moon",
+ "moonNextFullMoon": "次の満月",
"dpmSheetEmpty": "地図上のマーカーをタップして詳細を表示",
"onboardingSkipLeave": "このままスキップ",
"aedPlaceDesc": "設置場所",
@@ -582,22 +582,22 @@
},
"onboardingPermBattery": "バッテリー最適化の除外",
"typhoonLabelNw": "北西",
- "moonPhaseWaxingCrescent": "Waxing crescent",
+ "moonPhaseWaxingCrescent": "上弦",
"restroomCategoryLeisure": "レジャー・娯楽施設",
"mapLayerTemperature": "気温",
"aedCategory": "分類",
"@moonTimelineCaption": {
"description": "Moon phase timeline caption"
},
- "meshtasticChannels": "Channels",
+ "meshtasticChannels": "チャンネル",
"monitorWaiting": "データ待機中…",
"typhoonOverlayForecastCallouts": "予報点の情報",
"@meshtasticTitle": {
"description": "Meshtastic test page title"
},
"reportDetailEpicenter": "震央座標",
- "meshtasticVoltage": "Voltage",
- "mapLayerMeshtasticSubtitle": "LoRa mesh nodes heard by your radio",
+ "meshtasticVoltage": "電圧",
+ "mapLayerMeshtasticSubtitle": "無線機で受信した LoRa メッシュノード",
"@meshtasticSent": {
"description": "Packets sent this session"
},
@@ -640,7 +640,7 @@
"@meshtasticStateDisconnected": {
"description": "Connection state label"
},
- "meshtasticReceived": "Received",
+ "meshtasticReceived": "受信",
"weatherRankingExtremeLow": "今日の最低",
"@meshtasticRegionSwitch": {
"description": "Button applying the DPIP LoRa region"
@@ -649,8 +649,8 @@
"mapLayerSatelliteCloudProbablyCloudy": "おそらく雲",
"shelterCategoryLabel": "対象災害",
"mapLayerSatelliteTransparentNoWater": "≤ 0 = 透明(水域なし)",
- "meshtasticStateConnecting": "Connecting…",
- "moonTitle": "Moon",
+ "meshtasticStateConnecting": "接続中…",
+ "moonTitle": "月",
"weatherRankingGust": "突風",
"moreAppStore": "App Store",
"@meshtasticUndecoded": {
@@ -661,7 +661,7 @@
},
"moreServerStatus": "サーバー状態",
"notifySectionWeather": "天気",
- "meshtasticPreset": "Modem preset",
+ "meshtasticPreset": "モデムプリセット",
"dataSectionSeismic": "地震",
"changelogBodyEmpty": "このリリースの説明はありません。",
"changelogOpenOnGitHub": "GitHub で見る",
@@ -670,15 +670,15 @@
"regionNationwide": "全国",
"moreNotifyLog": "DPIP 通知送信履歴",
"regionCurrent": "現在地",
- "meshtasticNotConnected": "Not connected to a radio",
+ "meshtasticNotConnected": "無線機に接続されていません",
"weatherModeSnow": "雪",
- "mapLayerMeshtastic": "Meshtastic nodes",
+ "mapLayerMeshtastic": "Meshtastic ノード",
"moreDeveloper": "デバッグ情報",
"@qpesumsOverlayMenuTooltip": {
"description": "Tooltip for the QPESUMS forecast overlay-options chip beside the layer switcher."
},
"mapLayerSatelliteB14": "ひまわり 長波長赤外線(B14)",
- "meshtasticChannelUse": "Channel use",
+ "meshtasticChannelUse": "チャンネル使用率",
"mapNavLightning": "稲妻",
"homeForecastEmpty": "予報データがありません",
"sponsorOneTime": "一回限りの支援",
@@ -686,7 +686,7 @@
"onboardingPermBackground": "バックグラウンドの位置情報",
"aedEmergencyPhone": "緊急連絡先",
"dpmOpenInMaps": "地図アプリで開く",
- "meshtasticNotifyNodes": "Notify on new nodes",
+ "meshtasticNotifyNodes": "新しいノードで通知",
"onboardingPermCriticalDesc": "生命に関わる緊急地震速報を、消音モードやおやすみモードでも鳴らせるようにします。",
"@mapAppDefault": {
"placeholders": {
@@ -696,10 +696,10 @@
}
},
"mapLayerSatelliteTransparentWarm": "晴れ(暖域) = 透明、地図が透ける",
- "meshtasticSent": "Sent",
+ "meshtasticSent": "送信済み",
"homeForecastTitle": "24時間予報",
"typhoonLegendWarningAreas": "警報区域",
- "meshtasticExcludeMqttHidden": "{count} hidden",
+ "meshtasticExcludeMqttHidden": "{count} 件を非表示",
"notifyOptLocalIntensity1": "所在地の震度1以上",
"@skyTimeGolden": {
"description": "Label for the skyTimeGolden option in the experimental backdrop settings."
@@ -710,7 +710,7 @@
"mapTimelinePast": "過去",
"restroomTypeFemale": "女性用トイレ",
"reportListToday": "今日",
- "meshtasticTapNode": "Tap a node for details",
+ "meshtasticTapNode": "ノードをタップして詳細を表示",
"commonLoading": "読み込み中…",
"@meshtasticStateConnecting": {
"description": "Connection state label"
@@ -718,7 +718,7 @@
"typhoonIntensityModerate": "並の台風",
"mapLayerSatelliteAsh": "ひまわり 火山灰",
"rainInterval3h": "3時間",
- "meshtasticChannelReady": "DPIP channel ready",
+ "meshtasticChannelReady": "DPIP チャンネルの準備ができました",
"@meshtasticNotifyNodes": {
"description": "Toggle: local notification when a new node is heard"
},
@@ -773,7 +773,7 @@
}
},
"mapLayerSatelliteBtdSo2": "ひまわり 二酸化硫黄/雲相",
- "meshtasticStateError": "Error",
+ "meshtasticStateError": "エラー",
"weatherModeOvercast": "本曇り",
"@meshtasticScan": {
"description": "Start scanning for Meshtastic radios"
@@ -793,7 +793,7 @@
"description": "Transmit power"
},
"shelterOutdoorLabel": "屋外収容",
- "meshtasticStateConnected": "Connected",
+ "meshtasticStateConnected": "接続済み",
"mapNavRadar": "レーダー",
"mapLayerSatelliteCloudClear": "晴れ",
"eewSummary": "M{magnitude}・深さ {depth} km",
@@ -802,7 +802,7 @@
"radarCountyOutlineHint": "エコーの上に描画",
"windForecastCountyOutlineHint": "風場の上に描画",
"homeRainTrendTitle": "今後1時間の雨",
- "moonPhaseFirstQuarter": "First quarter",
+ "moonPhaseFirstQuarter": "上弦の月",
"mapLayerCategoryTyphoon": "台風",
"@windForecastOverlayMenuTooltip": {
"description": "Tooltip for the wind-forecast overlay-options chip beside the layer switcher."
@@ -810,13 +810,13 @@
"@meshtasticNodeId": {
"description": "The radio's node number"
},
- "meshtasticUtilization": "Airtime (24h)",
+ "meshtasticUtilization": "エアタイム(24h)",
"restroomTypeMixed": "男女共用トイレ",
"restroomGradeGood": "優良",
"notifyTsunami": "津波情報",
"navData": "データ",
"mapLayerSatelliteBtdWvirw": "ひまわり オーバーシューティングトップ",
- "meshtasticReadingAge": "Reading taken",
+ "meshtasticReadingAge": "計測時刻",
"@moonPhaseWaningGibbous": {
"description": "Phase: waning gibbous"
},
@@ -829,7 +829,7 @@
"notifyIntensity": "震度速報",
"rainIntervalMenu": "累積期間",
"reportDetailLocalFelt": "局地的な有感地震",
- "meshtasticDevice": "Device",
+ "meshtasticDevice": "デバイス",
"onboardingGrant": "許可",
"weatherModeRain": "雨",
"shelterVulnerableOkLabel": "要配慮者向け収容",
@@ -853,7 +853,7 @@
"trendCumulativeTotal": "累計 {total} mm",
"languageName": "日本語",
"reportListEmptyFiltered": "条件に一致する地震報告はありません",
- "meshtasticExcludeMqtt": "Hide MQTT nodes",
+ "meshtasticExcludeMqtt": "MQTT ノードを隠す",
"mapNavTyphoon": "台風",
"weatherModeSand": "砂じん",
"@moonPhaseFirstQuarter": {
@@ -869,9 +869,9 @@
"feedStale": "データが最新でない可能性があります",
"homeForecastWind": "{direction} · 風力{level}",
"navHome": "ホーム",
- "meshtasticRegionLabel": "Region",
+ "meshtasticRegionLabel": "地域",
"mapLayerSatelliteCloudtop": "ひまわり 雲頂温度",
- "moonTimelineCaption": "Phase",
+ "moonTimelineCaption": "月相",
"@meshtasticChannelNoSlot": {
"description": "Every secondary channel slot is taken"
},
@@ -886,7 +886,7 @@
"reportFilterSortDepth": "深さ",
"mapTimelineDataTime": "データ時刻 {time}",
"radarScanRange": "走査範囲を表示",
- "meshtasticHopLimit": "Hop limit",
+ "meshtasticHopLimit": "ホップ数上限",
"@meshtasticUptime": {
"description": "Time since the radio booted"
},
@@ -897,17 +897,17 @@
"sponsorPrivacy": "プライバシーポリシー",
"reportDetailLocalIntensity": "現在地の震度",
"mapLayerSatelliteNaturalcolor": "ひまわり ナチュラルカラー",
- "meshtasticAirtime": "Air time (TX)",
+ "meshtasticAirtime": "エアタイム(TX)",
"shelterCapacityValue": "{n} 人",
"lightningLegendCc": "雲間 · {minutes} 分以内",
- "meshtasticSendHint": "Message to broadcast",
+ "meshtasticSendHint": "送信するメッセージ",
"monitorDelay": "遅延 {value} s",
"@meshtasticFirmware": {
"description": "Firmware version"
},
"dpmNo": "いいえ",
"mapLayerSatelliteB08": "ひまわり 上層水蒸気(B08)",
- "meshtasticReconnecting": "Reconnecting…",
+ "meshtasticReconnecting": "再接続中…",
"@mapAppAppleMaps": {},
"@meshtasticReadingAge": {
"description": "How old the battery/airtime numbers are"
@@ -966,21 +966,21 @@
"endpointStateUnknown": "不明",
"endpointServiceEew": "EEW",
"endpointServiceRts": "RTS",
- "endpointServiceRadar": "Radar",
- "endpointServiceSatellite": "Satellite",
+ "endpointServiceRadar": "レーダー",
+ "endpointServiceSatellite": "衛星画像",
"endpointServiceQpesums": "QPE",
- "endpointServiceWind": "Wind",
- "endpointServiceDpm": "Disaster points",
- "endpointServiceWeather": "Weather",
- "endpointServiceRain": "Rain",
- "endpointServiceLightning": "Lightning",
- "endpointServiceTyphoon": "Typhoon",
- "endpointServiceReport": "EQ reports",
- "endpointServiceTremStation": "Tremor station",
- "endpointServiceEvent": "Events",
- "endpointServiceLocation": "Location",
- "endpointServiceNotify": "Notifications",
- "endpointServiceOther": "Other",
+ "endpointServiceWind": "風",
+ "endpointServiceDpm": "災害地点",
+ "endpointServiceWeather": "天気",
+ "endpointServiceRain": "雨",
+ "endpointServiceLightning": "雷",
+ "endpointServiceTyphoon": "台風",
+ "endpointServiceReport": "地震報告",
+ "endpointServiceTremStation": "震度計",
+ "endpointServiceEvent": "イベント",
+ "endpointServiceLocation": "位置情報",
+ "endpointServiceNotify": "通知",
+ "endpointServiceOther": "その他",
"feedConnecting": "接続中…",
"notifyBannerDisabled": "通知がオフです — 災害警報を受け取れません。",
"@meshtasticNoNodes": {
@@ -989,16 +989,16 @@
"weatherHumidity": "湿度",
"typhoonValueMs": "毎秒 {n} m",
"homeForecastHumidity": "湿度 {value}%",
- "meshtasticBusyBody": "Disconnect it in the other Meshtastic app first. Two apps on one radio take each other's messages, so some will go missing.",
- "meshtasticChannelNoSlot": "No free channel slot — free one on the radio",
+ "meshtasticBusyBody": "先に別の Meshtastic アプリで無線機を切断してください。1 台の無線機を 2 つのアプリで使うと互いのメッセージを奪い合い、一部が失われます。",
+ "meshtasticChannelNoSlot": "空きチャンネルがありません — 無線機で1つ空けてください",
"restroomCategoryTransport": "交通",
- "meshtasticBattery": "Battery",
+ "meshtasticBattery": "バッテリー",
"meshtasticDistance": "距離",
"meshtasticSnrTrend": "信号トレンド (SNR)",
"meshtasticBatteryTrend": "バッテリー推移",
"typhoonOverlayMenuTooltip": "台風オーバーレイ設定",
"mapLayerSatelliteBtdOzone": "ひまわり 対流圏界面",
- "meshtasticRegionMismatch": "Radio region is {region} — DPIP needs TW",
+ "meshtasticRegionMismatch": "無線機の地域は {region} です — DPIP は TW が必要です",
"notifySectionEarthquake": "地震",
"mapLayerDisasterMap": "防災マップ",
"weatherModeFog": "霧",
@@ -1007,9 +1007,10 @@
"moreAnnouncements": "お知らせ",
"moreTagline": "防災情報統合プラットフォーム",
"moreVersionStable": "正式版",
- "moreVersionNotes": "現在のバージョン",
+ "moreVersionNotes": "今回の更新",
+ "moreVersionNotesHighlightsSubtitle": "このバージョンでの変更点",
"releaseHighlightsSeeNotes": "完全なリリースノート",
- "releaseHighlightsTitle": "今回の更新",
+ "releaseHighlightsTitle": "{train} まとめ",
"releaseHighlightsTabNormal": "変更点",
"releaseHighlightsTabAdvanced": "技術詳細",
"releaseHighlightsEmpty": "まだコンテンツがありません。",
@@ -1052,7 +1053,7 @@
"onboardingPermsTitle": "権限の許可",
"mapLayerStyleJma": "雲頂強調(JMA)",
"rainInterval10m": "10分",
- "meshtasticConnectAnyway": "Connect anyway",
+ "meshtasticConnectAnyway": "接続する",
"reportListDayCount": "{count}",
"mapLayerSatelliteB06": "ひまわり 近赤外(B06)",
"mapLayerSatelliteTransparentReflectance": "低反射率・夜間 = 透明、地図が透ける",
@@ -1068,7 +1069,7 @@
"reportDetailSortByIntensity": "震度順に並べ替え",
"homeRainTrendNoData": "データなし",
"mapLayerCategoryRadar": "レーダー",
- "meshtasticShortName": "Short name",
+ "meshtasticShortName": "短縮名",
"@meshtasticStateConfiguring": {
"description": "Connection state label"
},
@@ -1088,7 +1089,7 @@
"@skyTimeMorning": {
"description": "Label for the skyTimeMorning option in the experimental backdrop settings."
},
- "meshtasticRegionConfirm": "Switch this radio to the TW region? It restarts and disconnects for a moment, and every other channel on it moves too.",
+ "meshtasticRegionConfirm": "この無線機を TW 地域に切り替えますか?再起動して一時的に切断され、他のチャンネルも移動します。",
"dataEarthquakeSubtitle": "地震報告",
"typhoonNoActive": "発生中の台風なし",
"@meshtasticExcludeMqttHidden": {
@@ -1105,10 +1106,55 @@
"@meshtasticChannels": {
"description": "Section: the radio's channel table"
},
+ "mapOsmOverlay": "詳細地図",
+ "mapOsmOverlayHint": "道路、建物、地名をより詳しく表示",
+ "mapOsmDetails": "詳細地図のレイヤー",
+ "moreDataSources": "データ提供元",
+ "dataSourceTremNet": "探索智慧科技有限公司 — TREM-Net",
+ "dataSourceCwa": "交通部中央氣象署 (CWA)",
+ "dataSourceJma": "気象庁 (JMA)",
+ "dataSourceNcdr": "國家災害防救科技中心 (NCDR)",
+ "dataSourceEcmwf": "European Centre for Medium-Range Weather Forecasts (ECMWF)",
+ "dataSourceNoaaGfs": "National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)",
+ "dataSourceGovernmentOpenData": "政府資料開放平臺",
+ "dataSourceOpenStreetMap": "© OpenStreetMap contributors",
+ "dataSourceNasaMoon": "National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)",
+ "mapOsmDetailsHint": "{enabled} / {total} レイヤーを有効化",
+ "@mapOsmDetailsHint": {
+ "description": "How many of the OSM layers are enabled",
+ "placeholders": {
+ "enabled": {
+ "type": "int"
+ },
+ "total": {
+ "type": "int"
+ }
+ }
+ },
+ "mapOsmSurface": "地表",
+ "mapOsmParks": "公園",
+ "mapOsmLandUse": "土地利用",
+ "mapOsmAirportAreas": "空港エリア",
+ "mapOsmWater": "水域",
+ "mapOsmRivers": "河川",
+ "mapOsmBoundaries": "境界",
+ "mapOsmBuildings": "建物",
+ "mapOsmRoads": "道路",
+ "mapOsmRoadNames": "道路名",
+ "mapOsmWaterNames": "水域名",
+ "mapOsmPeaks": "山頂",
+ "mapOsmAirportNames": "空港名",
+ "mapOsmPlaceNames": "地名",
+ "mapOsmPoi": "注目施設",
+ "mapOsmHouseNumbers": "住居表示",
+ "mapOsmRestoreAll": "すべて復元",
+ "mapOsmSectionNatural": "自然地物",
+ "mapOsmSectionRoadsAndBuildings": "道路と建物",
+ "mapOsmSectionLabelsAndPlaces": "ラベルと場所",
"mapTownLabels": "郷鎮名",
"notifySetFailed": "設定を保存できませんでした。もう一度お試しください。",
- "meshtasticDisconnect": "Disconnect",
- "meshtasticUndecoded": "Not decrypted",
+ "meshtasticDisconnect": "切断",
+ "meshtasticUndecoded": "復号されていません",
"notifyAnnouncement": "お知らせ",
"onboardingIntroTitle": "DPIP へようこそ",
"regionCurrentUnavailable": "現在地を取得できません",
@@ -1799,6 +1845,30 @@
"description": "Button that opens the system settings page"
},
"permissionSettingsMessage": "「{what}」は拒否されており、システムは再度確認しません。設定から許可してください。",
+ "permissionGuideNotification": "システム設定から通知を許可してください。",
+ "permissionGuideForegroundLocation": "システム設定から正確な位置情報を許可してください。",
+ "permissionGuideBackgroundLocation": "「{option}」で「常に許可」を選択してください。",
+ "@permissionGuideBackgroundLocation": {
+ "description": "Instruction for background location",
+ "placeholders": {
+ "option": {}
+ }
+ },
+ "permissionGuideBackgroundExecution": "システム設定でバックグラウンド実行を許可し、通知が停止されないようにしてください。",
+ "permissionGuideUnusedPause": "アプリが「未使用」と表示される場合は、システム設定で「許可」を選択してください。",
+ "permissionGuideUnusedFreeSpace": "ストレージ不足で一時停止された場合は、キャッシュを削除して再度開いてください。",
+ "permissionGuideUnusedRevoke": "アプリの権限が取り消された場合は、システム設定で再度許可してください。",
+ "permissionGuideUnusedPlayProtect": "Play プロテクトが一時停止した場合は、Google Play でアプリの状態を確認してください。",
+ "permissionGuideVendorPower": "「{vendor}」の省電力設定で、このアプリを「制限なし」に設定してください。",
+ "@permissionGuideVendorPower": {
+ "description": "Instruction for vendor power saving",
+ "placeholders": {
+ "vendor": {}
+ }
+ },
+ "permissionStillRequired": "まだ必要です。設定から有効にしてください。",
+ "permissionVerifyManually": "システム設定でこの権限が有効かどうか手動で確認してください。",
+ "permissionBackgroundLocationOption": "「常に許可」",
"@permissionSettingsMessage": {
"description": "Explains that the system will not ask again for this permission",
"placeholders": {
@@ -1872,6 +1942,9 @@
},
"moreDumpDiagnostics": "デバッグ情報とログを送信",
"moreDumpDiagnosticsHint": "アップロードしてリンクをコピーします",
+ "dumpIncludeSensitive": "正確な位置情報を含める",
+ "dumpIncludeSensitiveHint": "ログとバックグラウンド位置情報の座標を含めます。未選択の場合は null に置き換えます",
+ "dumpUpload": "アップロード",
"dumpUploaded": "アップロードしました",
"dumpLinkCopied": "リンクをクリップボードにコピーしました",
"dumpCopyAgain": "もう一度コピー",
diff --git a/lib/l10n/app_ko.arb b/lib/l10n/app_ko.arb
index 2cdb480e7..b46e9f804 100644
--- a/lib/l10n/app_ko.arb
+++ b/lib/l10n/app_ko.arb
@@ -19,29 +19,29 @@
"reportFilterIntensity": "진도",
"mapLayerLightning": "번개",
"restroomTypeMale": "남자 화장실",
- "meshtasticLastReceived": "Last received",
+ "meshtasticLastReceived": "마지막 수신",
"reportDetailSortByCounty": "지역순 정렬",
"@moonDays": {
"description": "Day unit for the moon age"
},
"homeRainTrendScattered": "약한 비가 올 수 있어요",
- "meshtasticUptime": "Uptime",
+ "meshtasticUptime": "가동 시간",
"weatherRankingTempExtremes": "기온 극값",
"themeLight": "라이트",
"mapTerrainReliefHint": "기본 지도에 지형 음영 표시",
- "meshtasticEmptyMessage": "(empty message)",
+ "meshtasticEmptyMessage": "(빈 메시지)",
"moreSectionRegion": "지역",
"mapLayerSatellite": "히마와리 적외(B13)",
"@meshtasticTapNode": {
"description": "Resting state of the map node sheet"
},
"aedHoursSaturday": "토요일 운영시간",
- "moonPhaseNew": "New moon",
+ "moonPhaseNew": "신월",
"notifySectionEew": "지진 조기경보",
"mapResetNorth": "북쪽으로 되돌리기",
"rainInterval2d": "2일",
"mapTownLabelsHint": "확대하면 읍면동 이름 표시",
- "commonCancel": "Cancel",
+ "commonCancel": "취소",
"notifyOptTsunamiWarning": "지진해일 경보만",
"mapLayerSatelliteBtdFog": "히마와리 야간 안개",
"@meshtasticSelectDevice": {
@@ -82,16 +82,16 @@
"changelogShowSnapshots": "스냅샷 표시",
"changelogTitle": "변경 로그",
"reportFilterOrderDesc": "내림차순",
- "meshtasticExcludeMqttSubtitle": "Nodes bridged over the internet, not heard by radio",
+ "meshtasticExcludeMqttSubtitle": "인터넷으로 연결된 노드(무선으로는 수신되지 않음)",
"reportFilterIntensityInfoTitle": "진도 신제·구제",
"mapLayerTyphoon": "태풍",
"radarOverlayMenuTooltip": "레이더 레이어 옵션",
"@meshtasticChannelUse": {
"description": "Share of airtime seen busy"
},
- "meshtasticNodes": "Nodes",
- "meshtasticSend": "Send",
- "typhoonOverlayStormL7Tooltip": "Level-7 wind field + average circle (purple)",
+ "meshtasticNodes": "노드",
+ "meshtasticSend": "보내기",
+ "typhoonOverlayStormL7Tooltip": "레벨 7 바람장 + 평균 반경(보라색)",
"aedType": "유형",
"termsOfService": "서비스 약관",
"typhoonLegendCircle25": "폭풍권 (10급)",
@@ -110,12 +110,12 @@
"@meshtasticExcludeMqttSubtitle": {
"description": "What an MQTT node is"
},
- "meshtasticFirmware": "Firmware",
+ "meshtasticFirmware": "펌웨어",
"@mapLayerMeshtastic": {
"description": "Map layer name: mesh nodes"
},
"reportFilterDateEndNote": "종료일: 당일 24:00(타이베이)",
- "meshtasticSilent": "Silent",
+ "meshtasticSilent": "무음",
"reportFilterSortMagnitude": "규모",
"mapLayerCategoryEarthquake": "지진",
"mapLayerSatelliteB12": "히마와리 오존(B12)",
@@ -144,12 +144,12 @@
"@radarCountyOutlineHint": {
"description": "Hint under the county-border toggle in the radar overlay menu."
},
- "meshtasticLayerOptions": "Node options",
+ "meshtasticLayerOptions": "노드 옵션",
"onboardingAgreeContinue": "동의하고 계속",
- "meshtasticNodeId": "Node ID",
+ "meshtasticNodeId": "노드 ID",
"commonRetry": "다시 시도",
"reportDetailNumbered": "번호 {number} 유의미 유감지진",
- "typhoonOverlayStormBandSubtitle": "With average circle",
+ "typhoonOverlayStormBandSubtitle": "평균 반경 포함",
"disasterMapOverlayRestroomTooltip": "공중화장실 표시",
"weatherRankingTitle": "관측 순위",
"homeRainTrendHeavySustained": "앞으로 1시간 동안 강한 비가 이어질 거예요",
@@ -161,12 +161,12 @@
"@meshtasticSilent": {
"description": "Legend: node known but not heard recently"
},
- "meshtasticChannelWorking": "Setting up the DPIP channel…",
- "meshtasticRegionSwitch": "Switch to TW",
+ "meshtasticChannelWorking": "DPIP 채널 설정 중…",
+ "meshtasticRegionSwitch": "TW 지역으로 전환",
"@meshtasticLastReceived": {
"description": "Age of the last received packet"
},
- "meshtasticTraffic": "Traffic",
+ "meshtasticTraffic": "트래픽",
"@meshtasticDpipChannel": {
"description": "Which channel DPIP payloads use"
},
@@ -177,7 +177,7 @@
},
"mapLayerHumidity": "습도",
"mapLayerSatelliteTransparentNight": "야간 = 투명,배경 지도 표시",
- "meshtasticScanning": "Scanning…",
+ "meshtasticScanning": "스캔 중…",
"@meshtasticDevice": {
"description": "Section: device identity"
},
@@ -202,7 +202,7 @@
"meshtasticEtaDays": "약 {n}일",
"meshtasticTitle": "Meshtastic",
"navMore": "더보기",
- "meshtasticDpipChannel": "DPIP channel",
+ "meshtasticDpipChannel": "DPIP 채널",
"disasterMapOverlaySectionLayers": "레이어",
"@moonPhaseWaningCrescent": {
"description": "Phase: waning crescent"
@@ -215,15 +215,15 @@
"description": "Label for the weatherModeCloudy option in the experimental backdrop settings."
},
"typhoonLabelNe": "NE",
- "meshtasticCopied": "Message copied",
+ "meshtasticCopied": "메시지를 복사했습니다",
"reportListEmpty": "지진 보고서가 없습니다",
"reportListEnd": "마지막입니다",
"mapLayerSatelliteTruecolor": "히마와리 트루컬러",
- "typhoonOverlaySectionExtra": "Overlays",
+ "typhoonOverlaySectionExtra": "오버레이",
"eewSWave": "S파",
- "meshtasticBusyTitle": "Another app is using this radio",
+ "meshtasticBusyTitle": "다른 앱이 이 무전기를 사용 중입니다",
"restroomCategoryCultural": "문화·여가 시설",
- "typhoonLabelWind": "Max. sustained wind near centre",
+ "typhoonLabelWind": "중심 부근 최대 지속 풍속",
"radarGlobalOutlineHint": "각국 국경선",
"notifyEvacuation": "재난 정보",
"typhoonLegendCircle15": "강풍권 (7급)",
@@ -233,11 +233,11 @@
"@meshtasticRadioSettings": {
"description": "Section: LoRa settings"
},
- "dataSectionAstronomy": "Astronomy",
+ "dataSectionAstronomy": "천문",
"homeRainTrendLightSustained": "앞으로 1시간 동안 약한 비가 이어질 거예요",
"commonError": "문제가 발생했습니다",
- "moonPhaseWaningCrescent": "Waning crescent",
- "meshtasticPower": "Power",
+ "moonPhaseWaningCrescent": "그믐달",
+ "meshtasticPower": "전원",
"@meshtasticChannelWorking": {
"description": "Creating/verifying the DPIP channel"
},
@@ -248,14 +248,14 @@
"typhoonWarningAreas": "대상 지역: {areas}",
"rainIntervalSection": "집계 시간",
"notifyTitle": "알림",
- "meshtasticTxPower": "TX power",
+ "meshtasticTxPower": "TX 전력",
"@radarTownOutlineHint": {
"description": "Hint under the township-border toggle in the radar overlay menu."
},
"restroomCategoryLabel": "구분",
"sponsorRestoring": "구매를 복원하는 중…",
"sponsorIntro": "DPIP는 실시간 재난 예방 정보를 제공하는 데 전념하며, 광고나 다른 수익 모델이 없습니다. 여러분의 후원은 서버 운영과 지속적인 개발에 도움이 됩니다.",
- "typhoonLabelStormAvg": "Avg. radius of Beaufort 10 winds",
+ "typhoonLabelStormAvg": "보퍼트 10 풍속 평균 반경",
"@meshtasticHardware": {
"description": "Board model"
},
@@ -274,7 +274,7 @@
"rainInterval6h": "6시간",
"homeRainTrendMinute": "{minute}분",
"restroomTypeUnspecified": "미설정",
- "typhoonOverlayProbabilityHint": "Hides the forecast cone",
+ "typhoonOverlayProbabilityHint": "예상 이동 경로를 숨깁니다",
"mapLayerSatelliteGlobalOutline": "국경선",
"mapNavTemperature": "온도",
"typhoonLegendForecastPoint": "예보 지점",
@@ -289,16 +289,16 @@
"rainInterval3d": "3일",
"defaultMapLayerSubtitle": "지도 탭을 열 때 표시할 레이어입니다. 하단 탐색 아이콘과 라벨도 함께 바뀝니다.",
"aedDescription": "비고",
- "typhoonOverlayWeatherRadarTooltip": "Radar echo closest to the typhoon bulletin time",
+ "typhoonOverlayWeatherRadarTooltip": "태풍 정보 시간과 가장 가까운 레이더 에코",
"onboardingPermLocationDesc": "현재 위치에 맞춰 경보를 전달합니다.",
"mapLayerSatelliteB16": "히마와리 이산화탄소(B16)",
"@meshtasticClearMessages": {
"description": "Menu action clearing the message log"
},
"homeActiveEventsEmpty": "발효 중인 이벤트가 없습니다",
- "typhoonLabelPosition": "Centre location",
+ "typhoonLabelPosition": "중심 위치",
"weatherRankingBy": "정렬",
- "typhoonIntensityMild": "Mild typhoon",
+ "typhoonIntensityMild": "약한 태풍",
"windForecastGlobalOutlineHint": "각국 국경선",
"rainInterval1h": "1시간",
"eewLocalIntensity": "현재 위치 예상",
@@ -307,14 +307,14 @@
"description": "Radar scan-range overlay toggle in the map's radar overlay menu."
},
"restroomCategoryReligious": "종교·의례 시설",
- "meshtasticRole": "Role",
+ "meshtasticRole": "역할",
"mapLayerSatelliteCloudCloudy": "구름",
"skyTimeSunrise": "일출",
"@mapLayerMeshtasticSubtitle": {
"description": "Map layer switcher subtitle"
},
"meshtasticJumpToLatest": "최신으로 이동",
- "meshtasticNoMessages": "No messages yet",
+ "meshtasticNoMessages": "아직 메시지가 없습니다",
"onboardingPermNotifyDesc": "지진, 날씨, 재해가 발생하는 즉시 경보를 전달합니다.",
"radarTownOutline": "읍·면·동 경계",
"mapLayerStyleSection": "색상 스타일",
@@ -323,7 +323,7 @@
},
"disasterMapOverlayMenuTooltip": "방재 지도 레이어",
"moreGooglePlay": "Google Play",
- "meshtasticOnline": "Heard recently",
+ "meshtasticOnline": "최근 수신됨",
"@meshtasticSendHint": {
"description": "Message input hint"
},
@@ -350,11 +350,11 @@
"mapLayerSatelliteTransparentNoVegetation": "< 0.1 = 투명(식생 없음)",
"notifyOptLocalIntensity4": "현재 위치 진도 4 이상",
"eewArrived": "도달",
- "meshtasticNoDevices": "No Meshtastic devices found",
+ "meshtasticNoDevices": "Meshtastic 기기를 찾을 수 없습니다",
"mapLayerCategoryLife": "생활",
"reportFilterSortIntensity": "진도",
- "meshtasticStateDisconnected": "Disconnected",
- "typhoonIntensityIntense": "Intense typhoon",
+ "meshtasticStateDisconnected": "연결 해제됨",
+ "typhoonIntensityIntense": "강한 태풍",
"@meshtasticSend": {
"description": "Send message button"
},
@@ -366,7 +366,7 @@
"description": "The radio's short name"
},
"dpmYes": "예",
- "meshtasticNoHistory": "Not enough history yet",
+ "meshtasticNoHistory": "아직 기록이 부족합니다",
"reportDetailLocalIntensityUnavailable": "진도 정보 없음",
"mapLayerWindForecastGfs": "GFS",
"reportFilterDepth": "깊이",
@@ -390,8 +390,8 @@
},
"reportFilterReset": "초기화",
"mapLayerSatelliteMndwi": "히마와리 MNDWI",
- "typhoonOverlaySectionStorm": "Storm wind",
- "moonPhaseFull": "Full moon",
+ "typhoonOverlaySectionStorm": "폭풍 바람",
+ "moonPhaseFull": "보름달",
"@meshtasticEmptyMessage": {
"description": "Placeholder for a text packet with no body"
},
@@ -399,24 +399,24 @@
"@radarGlobalOutlineHint": {
"description": "Hint under the national-border toggle in the radar overlay menu."
},
- "moonPhaseWaningGibbous": "Waning gibbous",
+ "moonPhaseWaningGibbous": "하현망월",
"reportFilterIntensityInfoModernTitle": "신제(2020년 이후)",
"@mapAppGoogleMaps": {},
- "typhoonDataTime": "Data time\n{time}",
+ "typhoonDataTime": "자료 시간\n{time}",
"restroomTypeAccessible": "장애인 화장실",
"moreSectionAbout": "정보",
- "meshtasticSelectDevice": "Select a radio",
+ "meshtasticSelectDevice": "무전기 선택",
"onboardingIntroBody": "DPIP는 여러분과 함께하는 방재 파트너입니다. 지진 조기경보, 지진 보고, 날씨, 각종 재해 정보를 통합하여 중요한 순간에 실시간으로 알려드립니다.\n\n• 지진: 지진 조기경보, 진도 속보, 상세 지진 보고\n• 날씨: 뇌우 실시간 메시지, 기상 특보\n• 지진해일 및 재난 정보\n\n다음으로, 서비스 약관을 확인하고 DPIP가 실시간으로 여러분을 보호할 수 있도록 몇 가지 권한을 허용해 주시기 바랍니다.",
"shelterCapacityLabel": "수용 인원",
"reportDetailImage": "지진 보고서 이미지",
- "meshtasticStateConfiguring": "Configuring…",
+ "meshtasticStateConfiguring": "구성 중…",
"@moonPhaseLastQuarter": {
"description": "Phase: last quarter"
},
- "typhoonLabelGaleAvg": "Avg. radius of Beaufort 7 winds",
+ "typhoonLabelGaleAvg": "보퍼트 7 풍속 평균 반경",
"onboardingPermNotify": "알림",
- "meshtasticClearMessages": "Clear messages",
- "meshtasticNotifyMessages": "Notify on new messages",
+ "meshtasticClearMessages": "메시지 지우기",
+ "meshtasticNotifyMessages": "새 메시지 알림",
"defaultMapLayerSettings": "지도 기본 레이어",
"eewSourceSettings": "지진 조기경보 출처",
"eewSourceSubtitle": "표시할 지진 조기경보 발표 기관을 선택하세요.",
@@ -446,7 +446,7 @@
"description": "Label for the skyTimeAfternoon option in the experimental backdrop settings."
},
"mapTimelineFuture": "미래",
- "typhoonLegendCircleAvg": "Average circle",
+ "typhoonLegendCircleAvg": "평균 반경",
"reportFilterDepthKm": "{depth} km",
"typhoonLabelSe": "SE",
"radarTownOutlineHint": "더 세밀한 구획",
@@ -454,7 +454,7 @@
"@meshtasticDisconnect": {
"description": "Disconnect from the radio"
},
- "typhoonLabelGust": "Peak gust",
+ "typhoonLabelGust": "최대 돌풍",
"mapAppGoogleMaps": "Google Maps",
"sponsorTerms": "이용약관",
"restroomTypeGenderNeutral": "성중립 화장실",
@@ -463,7 +463,7 @@
},
"notifyThunderstorm": "뇌우 알림",
"skyTimeGolden": "골든아워",
- "moonAge": "Age",
+ "moonAge": "월령",
"@windForecastTownOutlineHint": {
"description": "Hint under the township-border toggle in the wind-forecast overlay menu."
},
@@ -474,20 +474,20 @@
"moreGithub": "ExpTech GitHub",
"homeForecastUnavailable": "지역을 선택하면 예보를 볼 수 있습니다",
"mapLayers": "레이어",
- "meshtasticHardware": "Hardware",
+ "meshtasticHardware": "하드웨어",
"languageSettings": "언어",
"@moonNextFullMoon": {
"description": "Next full moon date label"
},
"language": "언어",
"homeForecastFeelsLike": "체감 {temp}°",
- "typhoonOverlayWeatherHint": "Aligned to bulletin time",
+ "typhoonOverlayWeatherHint": "정보 시간에 맞춤",
"@meshtasticHopLimit": {
"description": "How many hops a packet may take"
},
"skyTimeDawn": "여명",
"skyTimeAfternoon": "오후",
- "meshtasticLastHeard": "Last heard",
+ "meshtasticLastHeard": "마지막 수신",
"typhoonWarningTitle": "태풍 경보",
"moreSourceCode": "소스 코드",
"mapLayerCategoryWeather": "기상 관측",
@@ -506,37 +506,37 @@
"mapTimelineForecast": "예보",
"restroomTypeLabel": "유형",
"navEarthquake": "지진",
- "typhoonOverlayStormL10Tooltip": "Level-10 wind field + average circle (yellow)",
- "moonPhaseWaxingGibbous": "Waxing gibbous",
+ "typhoonOverlayStormL10Tooltip": "레벨 10 바람장 + 평균 반경(노란색)",
+ "moonPhaseWaxingGibbous": "상현망월",
"reportDetailTitle": "지진 보고서",
"moreTremReport": "TREM 탐지 보고",
"weatherDataTime": "{station} · 데이터 시간 {time}",
- "meshtasticNoNodes": "No nodes heard yet",
- "meshtasticViaMqtt": "Via MQTT (internet)",
+ "meshtasticNoNodes": "아직 노드가 감지되지 않았습니다",
+ "meshtasticViaMqtt": "MQTT 경유(인터넷)",
"radarCountyOutline": "시·군 경계",
"@mapAppCopyCoordinates": {},
"commonClose": "닫기",
"restroomGradeLabel": "등급",
"rainIntervalNow": "오늘",
"changelogCurrentVersion": "현재",
- "typhoonOverlayForecastCalloutsTooltip": "Show forecast-point detail cards when zoomed in",
- "typhoonLabelPressure": "Central pressure",
+ "typhoonOverlayForecastCalloutsTooltip": "확대 시 예상 지점 상세 카드 표시",
+ "typhoonLabelPressure": "중심 기압",
"aedOpenRemark": "운영시간 비고",
"onboardingPermsBody": "재해가 발생하는 즉시 알려드릴 수 있도록 다음 권한을 허용해 주세요. 시스템 설정에서 언제든지 변경할 수 있습니다.",
- "typhoonOverlaySectionWeather": "Weather underlay",
+ "typhoonOverlaySectionWeather": "날씨 배경",
"@meshtasticStateConnected": {
"description": "Connection state label"
},
"notifyOptWeatherLocal": "현재 위치만",
"mapNavRain": "강우",
- "moonDays": "days",
+ "moonDays": "일",
"mapLegendUnit": "단위: {unit}",
"weatherModeClear": "맑음",
- "meshtasticRadio": "Radio",
+ "meshtasticRadio": "무전기",
"commonEmpty": "표시할 내용이 없습니다",
"mapLayerSatelliteB01": "히마와리 가시 청색(B01)",
- "meshtasticExternalPower": "External power",
- "moonPhaseLastQuarter": "Last quarter",
+ "meshtasticExternalPower": "외부 전원",
+ "moonPhaseLastQuarter": "하현",
"@meshtasticName": {
"description": "The radio's long name"
},
@@ -551,20 +551,20 @@
"mapLayerRestroom": "공중화장실",
"restroomCategoryWelfare": "사회복지 기관·집회 시설",
"restroomGradeExcellent": "최우수",
- "meshtasticLastSent": "Last sent",
- "meshtasticName": "Name",
- "meshtasticScan": "Scan",
+ "meshtasticLastSent": "마지막 전송",
+ "meshtasticName": "이름",
+ "meshtasticScan": "스캔",
"@radarOverlayMenuTooltip": {
"description": "Tooltip for the radar overlay-options chip beside the layer switcher"
},
"mapLayerCategoryForecast": "수치 예보",
- "meshtasticChannelFailed": "Couldn't set up the DPIP channel",
+ "meshtasticChannelFailed": "DPIP 채널을 설정하지 못했습니다",
"themeSystem": "시스템",
"mapLayerSatelliteNdvi": "히마와리 NDVI",
"typhoonLegendForecast": "예보 경로",
"typhoonValueHpa": "{n} hPa",
"weatherPrecipitation": "강수량",
- "moonNextFullMoon": "Next full moon",
+ "moonNextFullMoon": "다음 보름달",
"dpmSheetEmpty": "지도에서 마커를 눌러 상세 보기",
"onboardingSkipLeave": "그래도 건너뛰기",
"aedPlaceDesc": "설치 위치",
@@ -582,22 +582,22 @@
},
"onboardingPermBattery": "배터리 최적화 제외",
"typhoonLabelNw": "NW",
- "moonPhaseWaxingCrescent": "Waxing crescent",
+ "moonPhaseWaxingCrescent": "초승달",
"restroomCategoryLeisure": "휴양·오락 시설",
"mapLayerTemperature": "기온",
"aedCategory": "분류",
"@moonTimelineCaption": {
"description": "Moon phase timeline caption"
},
- "meshtasticChannels": "Channels",
+ "meshtasticChannels": "채널",
"monitorWaiting": "데이터 대기 중…",
- "typhoonOverlayForecastCallouts": "Forecast tooltips",
+ "typhoonOverlayForecastCallouts": "예상 도구 설명",
"@meshtasticTitle": {
"description": "Meshtastic test page title"
},
"reportDetailEpicenter": "진앙 좌표",
- "meshtasticVoltage": "Voltage",
- "mapLayerMeshtasticSubtitle": "LoRa mesh nodes heard by your radio",
+ "meshtasticVoltage": "전압",
+ "mapLayerMeshtasticSubtitle": "무전기로 들은 LoRa 메시 노드",
"@meshtasticSent": {
"description": "Packets sent this session"
},
@@ -631,7 +631,7 @@
"weatherModeThunderstorm": "뇌우",
"homeViewOnMap": "지도에서 보기",
"reportFilterIntensityInfoLegacyTitle": "구제(2020년 이전)",
- "typhoonLabelSpeed": "Past movement speed",
+ "typhoonLabelSpeed": "이동 속도",
"@meshtasticReconnecting": {
"description": "The link dropped and is being re-established"
},
@@ -640,7 +640,7 @@
"@meshtasticStateDisconnected": {
"description": "Connection state label"
},
- "meshtasticReceived": "Received",
+ "meshtasticReceived": "수신",
"weatherRankingExtremeLow": "오늘 최저",
"@meshtasticRegionSwitch": {
"description": "Button applying the DPIP LoRa region"
@@ -649,8 +649,8 @@
"mapLayerSatelliteCloudProbablyCloudy": "아마 구름",
"shelterCategoryLabel": "적용 재해",
"mapLayerSatelliteTransparentNoWater": "≤ 0 = 투명(수역 없음)",
- "meshtasticStateConnecting": "Connecting…",
- "moonTitle": "Moon",
+ "meshtasticStateConnecting": "연결 중…",
+ "moonTitle": "달",
"weatherRankingGust": "돌풍",
"moreAppStore": "App Store",
"@meshtasticUndecoded": {
@@ -661,7 +661,7 @@
},
"moreServerStatus": "서버 상태",
"notifySectionWeather": "날씨",
- "meshtasticPreset": "Modem preset",
+ "meshtasticPreset": "모뎀 프리셋",
"dataSectionSeismic": "지진",
"changelogBodyEmpty": "이 릴리스에 대한 설명이 없습니다.",
"changelogOpenOnGitHub": "GitHub에서 보기",
@@ -670,15 +670,15 @@
"regionNationwide": "전국",
"moreNotifyLog": "DPIP 알림 발송 기록",
"regionCurrent": "현재 위치",
- "meshtasticNotConnected": "Not connected to a radio",
+ "meshtasticNotConnected": "무전기에 연결되지 않음",
"weatherModeSnow": "눈",
- "mapLayerMeshtastic": "Meshtastic nodes",
+ "mapLayerMeshtastic": "Meshtastic 노드",
"moreDeveloper": "디버그 정보",
"@qpesumsOverlayMenuTooltip": {
"description": "Tooltip for the QPESUMS forecast overlay-options chip beside the layer switcher."
},
"mapLayerSatelliteB14": "히마와리 장파 적외(B14)",
- "meshtasticChannelUse": "Channel use",
+ "meshtasticChannelUse": "채널 사용률",
"mapNavLightning": "번개",
"homeForecastEmpty": "예보 데이터가 없습니다",
"sponsorOneTime": "일회성 후원",
@@ -686,7 +686,7 @@
"onboardingPermBackground": "백그라운드 위치",
"aedEmergencyPhone": "비상 연락처",
"dpmOpenInMaps": "지도에서 열기",
- "meshtasticNotifyNodes": "Notify on new nodes",
+ "meshtasticNotifyNodes": "새 노드 알림",
"onboardingPermCriticalDesc": "생명을 위협하는 지진 경보가 무음 모드나 방해 금지 모드에서도 소리를 낼 수 있도록 합니다.",
"@mapAppDefault": {
"placeholders": {
@@ -696,10 +696,10 @@
}
},
"mapLayerSatelliteTransparentWarm": "맑음(고온부) = 투명,배경 지도 표시",
- "meshtasticSent": "Sent",
+ "meshtasticSent": "전송됨",
"homeForecastTitle": "24시간 예보",
"typhoonLegendWarningAreas": "경보 지역",
- "meshtasticExcludeMqttHidden": "{count} hidden",
+ "meshtasticExcludeMqttHidden": "{count}개 숨김",
"notifyOptLocalIntensity1": "현재 위치 진도 1 이상",
"@skyTimeGolden": {
"description": "Label for the skyTimeGolden option in the experimental backdrop settings."
@@ -710,21 +710,21 @@
"mapTimelinePast": "과거",
"restroomTypeFemale": "여자 화장실",
"reportListToday": "오늘",
- "meshtasticTapNode": "Tap a node for details",
+ "meshtasticTapNode": "노드를 탭하여 자세히 보기",
"commonLoading": "불러오는 중…",
"@meshtasticStateConnecting": {
"description": "Connection state label"
},
- "typhoonIntensityModerate": "Moderate typhoon",
+ "typhoonIntensityModerate": "중간 강도 태풍",
"mapLayerSatelliteAsh": "히마와리 화산재",
"rainInterval3h": "3시간",
- "meshtasticChannelReady": "DPIP channel ready",
+ "meshtasticChannelReady": "DPIP 채널 준비 완료",
"@meshtasticNotifyNodes": {
"description": "Toggle: local notification when a new node is heard"
},
"mapLayerCategorySatellite": "위성",
"mapLayerSatelliteNightmicrophysics": "히마와리 야간 미세물리",
- "typhoonIntensityTd": "Tropical depression",
+ "typhoonIntensityTd": "열대 저기압",
"reportFilterDate": "날짜",
"sponsorRestoreUnavailable": "스토어에 연결할 수 없습니다. 나중에 다시 시도해 주세요.",
"homeForecastPop": "{pop}%",
@@ -773,13 +773,13 @@
}
},
"mapLayerSatelliteBtdSo2": "히마와리 이산화황/구름상",
- "meshtasticStateError": "Error",
+ "meshtasticStateError": "오류",
"weatherModeOvercast": "흐림",
"@meshtasticScan": {
"description": "Start scanning for Meshtastic radios"
},
"reportDetailDepth": "진원 깊이",
- "typhoonOverlayWarningTooltip": "Highlight counties under a typhoon warning",
+ "typhoonOverlayWarningTooltip": "태풍 경보 지역 강조",
"reportFilterDatePick": "날짜 선택",
"onboardingSkipStay": "돌아가기",
"@moonPhaseWaxingCrescent": {
@@ -793,16 +793,16 @@
"description": "Transmit power"
},
"shelterOutdoorLabel": "실외 수용",
- "meshtasticStateConnected": "Connected",
+ "meshtasticStateConnected": "연결됨",
"mapNavRadar": "레이더",
"mapLayerSatelliteCloudClear": "맑음",
"eewSummary": "규모 {magnitude} · 깊이 {depth} km",
"locationBannerPermission": "위치 권한이 꺼져 있어 지역 맞춤 경보를 받을 수 없습니다.",
- "typhoonOverlayWeatherNoneTooltip": "No radar or infrared underlay",
+ "typhoonOverlayWeatherNoneTooltip": "레이더 또는 적외선 배경 없음",
"radarCountyOutlineHint": "에코 위에 표시",
"windForecastCountyOutlineHint": "바람장 위에 표시",
"homeRainTrendTitle": "향후 1시간 강수",
- "moonPhaseFirstQuarter": "First quarter",
+ "moonPhaseFirstQuarter": "상현",
"mapLayerCategoryTyphoon": "태풍",
"@windForecastOverlayMenuTooltip": {
"description": "Tooltip for the wind-forecast overlay-options chip beside the layer switcher."
@@ -810,13 +810,13 @@
"@meshtasticNodeId": {
"description": "The radio's node number"
},
- "meshtasticUtilization": "Airtime (24h)",
+ "meshtasticUtilization": "에어타임(24시간)",
"restroomTypeMixed": "남녀 공용 화장실",
"restroomGradeGood": "우수",
"notifyTsunami": "지진해일 정보",
"navData": "자료",
"mapLayerSatelliteBtdWvirw": "히마와리 오버슈팅 탑",
- "meshtasticReadingAge": "Reading taken",
+ "meshtasticReadingAge": "측정 시각",
"@moonPhaseWaningGibbous": {
"description": "Phase: waning gibbous"
},
@@ -829,7 +829,7 @@
"notifyIntensity": "진도 속보",
"rainIntervalMenu": "누적 구간",
"reportDetailLocalFelt": "국지적 유감지진",
- "meshtasticDevice": "Device",
+ "meshtasticDevice": "기기",
"onboardingGrant": "허용",
"weatherModeRain": "비",
"shelterVulnerableOkLabel": "취약계층 수용 가능",
@@ -853,7 +853,7 @@
"trendCumulativeTotal": "누적 {total} mm",
"languageName": "한국어",
"reportListEmptyFiltered": "조건에 맞는 지진 보고서가 없습니다",
- "meshtasticExcludeMqtt": "Hide MQTT nodes",
+ "meshtasticExcludeMqtt": "MQTT 노드 숨기기",
"mapNavTyphoon": "태풍",
"weatherModeSand": "황사",
"@moonPhaseFirstQuarter": {
@@ -869,9 +869,9 @@
"feedStale": "데이터가 오래되었을 수 있습니다",
"homeForecastWind": "{direction} · 풍력 {level}",
"navHome": "홈",
- "meshtasticRegionLabel": "Region",
+ "meshtasticRegionLabel": "지역",
"mapLayerSatelliteCloudtop": "히마와리 운정 온도",
- "moonTimelineCaption": "Phase",
+ "moonTimelineCaption": "위상",
"@meshtasticChannelNoSlot": {
"description": "Every secondary channel slot is taken"
},
@@ -886,7 +886,7 @@
"reportFilterSortDepth": "깊이",
"mapTimelineDataTime": "데이터 시간 {time}",
"radarScanRange": "스캔 범위 표시",
- "meshtasticHopLimit": "Hop limit",
+ "meshtasticHopLimit": "홉 제한",
"@meshtasticUptime": {
"description": "Time since the radio booted"
},
@@ -897,17 +897,17 @@
"sponsorPrivacy": "개인정보 처리방침",
"reportDetailLocalIntensity": "내 위치의 진도",
"mapLayerSatelliteNaturalcolor": "히마와리 내추럴컬러",
- "meshtasticAirtime": "Air time (TX)",
+ "meshtasticAirtime": "에어타임(TX)",
"shelterCapacityValue": "{n} 명",
"lightningLegendCc": "구름 사이 · {minutes}분 이내",
- "meshtasticSendHint": "Message to broadcast",
+ "meshtasticSendHint": "브로드캐스트할 메시지",
"monitorDelay": "지연 {value} s",
"@meshtasticFirmware": {
"description": "Firmware version"
},
"dpmNo": "아니요",
"mapLayerSatelliteB08": "히마와리 상층 수증기(B08)",
- "meshtasticReconnecting": "Reconnecting…",
+ "meshtasticReconnecting": "다시 연결 중…",
"@mapAppAppleMaps": {},
"@meshtasticReadingAge": {
"description": "How old the battery/airtime numbers are"
@@ -916,9 +916,9 @@
"@moonPhaseWaxingGibbous": {
"description": "Phase: waxing gibbous"
},
- "typhoonOverlayWeatherSatelliteTooltip": "Infrared closest to the typhoon bulletin time",
+ "typhoonOverlayWeatherSatelliteTooltip": "태풍 정보 시간과 가장 가까운 적외선",
"radarScanRangeHint": "범위 밖 공백은 미관측",
- "typhoonPickerTd": "Tropical depression TD {no}",
+ "typhoonPickerTd": "열대 저기압 TD {no}",
"mapLayerSatelliteWatervapor": "히마와리 수증기",
"regionAddButton": "지역 추가",
"displaySettings": "화면",
@@ -966,21 +966,21 @@
"endpointStateUnknown": "알 수 없음",
"endpointServiceEew": "EEW",
"endpointServiceRts": "RTS",
- "endpointServiceRadar": "Radar",
- "endpointServiceSatellite": "Satellite",
+ "endpointServiceRadar": "레이더",
+ "endpointServiceSatellite": "위성",
"endpointServiceQpesums": "QPE",
- "endpointServiceWind": "Wind",
- "endpointServiceDpm": "Disaster points",
- "endpointServiceWeather": "Weather",
- "endpointServiceRain": "Rain",
- "endpointServiceLightning": "Lightning",
- "endpointServiceTyphoon": "Typhoon",
- "endpointServiceReport": "EQ reports",
- "endpointServiceTremStation": "Tremor station",
- "endpointServiceEvent": "Events",
- "endpointServiceLocation": "Location",
- "endpointServiceNotify": "Notifications",
- "endpointServiceOther": "Other",
+ "endpointServiceWind": "바람",
+ "endpointServiceDpm": "재해 지점",
+ "endpointServiceWeather": "날씨",
+ "endpointServiceRain": "비",
+ "endpointServiceLightning": "번개",
+ "endpointServiceTyphoon": "태풍",
+ "endpointServiceReport": "지진 보고",
+ "endpointServiceTremStation": "진도 관측소",
+ "endpointServiceEvent": "이벤트",
+ "endpointServiceLocation": "위치",
+ "endpointServiceNotify": "알림",
+ "endpointServiceOther": "기타",
"feedConnecting": "연결 중…",
"notifyBannerDisabled": "알림이 꺼져 있어 재난 경보를 받을 수 없습니다.",
"@meshtasticNoNodes": {
@@ -989,16 +989,16 @@
"weatherHumidity": "습도",
"typhoonValueMs": "{n} m/s",
"homeForecastHumidity": "습도 {value}%",
- "meshtasticBusyBody": "Disconnect it in the other Meshtastic app first. Two apps on one radio take each other's messages, so some will go missing.",
- "meshtasticChannelNoSlot": "No free channel slot — free one on the radio",
+ "meshtasticBusyBody": "먼저 다른 Meshtastic 앱에서 무전기를 연결 해제하세요. 무전기 하나를 두 앱이 함께 쓰면 서로의 메시지를 가로채 일부가 유실됩니다.",
+ "meshtasticChannelNoSlot": "빈 채널 슬롯이 없습니다 — 무전기에서 하나를 비우세요",
"restroomCategoryTransport": "교통",
- "meshtasticBattery": "Battery",
+ "meshtasticBattery": "배터리",
"meshtasticDistance": "거리",
"meshtasticSnrTrend": "신호 추이 (SNR)",
"meshtasticBatteryTrend": "배터리 추이",
- "typhoonOverlayMenuTooltip": "Typhoon overlay options",
+ "typhoonOverlayMenuTooltip": "태풍 오버레이 옵션",
"mapLayerSatelliteBtdOzone": "히마와리 대류권계면",
- "meshtasticRegionMismatch": "Radio region is {region} — DPIP needs TW",
+ "meshtasticRegionMismatch": "무전기 지역은 {region}입니다 — DPIP는 TW가 필요합니다",
"notifySectionEarthquake": "지진",
"mapLayerDisasterMap": "방재 지도",
"weatherModeFog": "안개",
@@ -1007,9 +1007,10 @@
"moreAnnouncements": "공지사항",
"moreTagline": "재해 정보 통합 플랫폼",
"moreVersionStable": "정식 버전",
- "moreVersionNotes": "현재 버전",
+ "moreVersionNotes": "이번 업데이트",
+ "moreVersionNotesHighlightsSubtitle": "이번 버전의 변경 사항",
"releaseHighlightsSeeNotes": "전체 릴리스 노트",
- "releaseHighlightsTitle": "이번 업데이트",
+ "releaseHighlightsTitle": "{train} 주요 내용",
"releaseHighlightsTabNormal": "변경된 점",
"releaseHighlightsTabAdvanced": "기술 세부",
"releaseHighlightsEmpty": "아직 내용이 없습니다.",
@@ -1025,10 +1026,10 @@
"mapLayerAed": "AED",
"changelogTypePrerelease": "베타",
"reportFilterIntensityInfoModernBody": "진도는 0–4, 5약, 5강, 6약, 6강, 7입니다. 필터는 신제를 따르며, 이전 지진은 목록에서 구제 표기로 표시됩니다.",
- "typhoonOverlayWeatherNone": "None",
+ "typhoonOverlayWeatherNone": "없음",
"mapLayerStyleGray": "그레이스케일(JMA)",
"weatherModeAuto": "자동",
- "typhoonLabelProbCircle": "70% probability circle",
+ "typhoonLabelProbCircle": "70% 확률 원",
"@radarCountyOutline": {
"description": "County-border overlay toggle in the map's radar overlay menu."
},
@@ -1038,7 +1039,7 @@
"@skyTimeSunrise": {
"description": "Label for the skyTimeSunrise option in the experimental backdrop settings."
},
- "typhoonLabelDirection": "Past movement direction",
+ "typhoonLabelDirection": "이동 방향",
"@meshtasticLastSent": {
"description": "Age of the last sent packet"
},
@@ -1052,13 +1053,13 @@
"onboardingPermsTitle": "권한 허용",
"mapLayerStyleJma": "운정 강조(JMA)",
"rainInterval10m": "10분",
- "meshtasticConnectAnyway": "Connect anyway",
+ "meshtasticConnectAnyway": "그래도 연결",
"reportListDayCount": "{count}",
"mapLayerSatelliteB06": "히마와리 근적외(B06)",
"mapLayerSatelliteTransparentReflectance": "낮은 반사율/야간 = 투명,배경 지도 표시",
"chartHourLabel": "{hour}시",
"mapLayerShelter": "대피소",
- "typhoonOverlayProbabilityTooltip": "Show strike probability (hides the forecast cone)",
+ "typhoonOverlayProbabilityTooltip": "강타 확률 표시(예상 이동 경로 숨김)",
"mapLayerSatelliteNdwi": "히마와리 NDWI",
"disasterMapOverlayShelterTooltip": "대피소 표시",
"mapNavHumidity": "습도",
@@ -1068,7 +1069,7 @@
"reportDetailSortByIntensity": "진도순 정렬",
"homeRainTrendNoData": "데이터 없음",
"mapLayerCategoryRadar": "레이더",
- "meshtasticShortName": "Short name",
+ "meshtasticShortName": "짧은 이름",
"@meshtasticStateConfiguring": {
"description": "Connection state label"
},
@@ -1088,7 +1089,7 @@
"@skyTimeMorning": {
"description": "Label for the skyTimeMorning option in the experimental backdrop settings."
},
- "meshtasticRegionConfirm": "Switch this radio to the TW region? It restarts and disconnects for a moment, and every other channel on it moves too.",
+ "meshtasticRegionConfirm": "이 무전기를 TW 지역으로 전환할까요? 잠시 재시작되고 연결이 끊기며, 다른 모든 채널도 이동합니다.",
"dataEarthquakeSubtitle": "지진 보고서",
"typhoonNoActive": "활성 태풍 없음",
"@meshtasticExcludeMqttHidden": {
@@ -1105,10 +1106,55 @@
"@meshtasticChannels": {
"description": "Section: the radio's channel table"
},
+ "mapOsmOverlay": "상세 지도",
+ "mapOsmOverlayHint": "도로, 건물 및 지명을 더 자세히 표시",
+ "mapOsmDetails": "상세 지도 레이어",
+ "moreDataSources": "데이터 출처",
+ "dataSourceTremNet": "探索智慧科技有限公司 — TREM-Net",
+ "dataSourceCwa": "交通部中央氣象署 (CWA)",
+ "dataSourceJma": "気象庁 (JMA)",
+ "dataSourceNcdr": "國家災害防救科技中心 (NCDR)",
+ "dataSourceEcmwf": "European Centre for Medium-Range Weather Forecasts (ECMWF)",
+ "dataSourceNoaaGfs": "National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)",
+ "dataSourceGovernmentOpenData": "政府資料開放平臺",
+ "dataSourceOpenStreetMap": "© OpenStreetMap contributors",
+ "dataSourceNasaMoon": "National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)",
+ "mapOsmDetailsHint": "{enabled} / {total}개 레이어 사용 중",
+ "@mapOsmDetailsHint": {
+ "description": "How many of the OSM layers are enabled",
+ "placeholders": {
+ "enabled": {
+ "type": "int"
+ },
+ "total": {
+ "type": "int"
+ }
+ }
+ },
+ "mapOsmSurface": "지표면",
+ "mapOsmParks": "공원",
+ "mapOsmLandUse": "토지 이용",
+ "mapOsmAirportAreas": "공항 지역",
+ "mapOsmWater": "수역",
+ "mapOsmRivers": "하천",
+ "mapOsmBoundaries": "경계",
+ "mapOsmBuildings": "건물",
+ "mapOsmRoads": "도로",
+ "mapOsmRoadNames": "도로명",
+ "mapOsmWaterNames": "수역 이름",
+ "mapOsmPeaks": "봉우리",
+ "mapOsmAirportNames": "공항 이름",
+ "mapOsmPlaceNames": "지명",
+ "mapOsmPoi": "관심 지점",
+ "mapOsmHouseNumbers": "건물 번호",
+ "mapOsmRestoreAll": "모두 복원",
+ "mapOsmSectionNatural": "자연 지형",
+ "mapOsmSectionRoadsAndBuildings": "도로 및 건물",
+ "mapOsmSectionLabelsAndPlaces": "레이블 및 장소",
"mapTownLabels": "읍면동 이름",
"notifySetFailed": "설정을 저장하지 못했습니다. 다시 시도해 주세요.",
- "meshtasticDisconnect": "Disconnect",
- "meshtasticUndecoded": "Not decrypted",
+ "meshtasticDisconnect": "연결 해제",
+ "meshtasticUndecoded": "복호화되지 않음",
"notifyAnnouncement": "공지사항",
"onboardingIntroTitle": "DPIP에 오신 것을 환영합니다",
"regionCurrentUnavailable": "현재 위치를 가져올 수 없습니다",
@@ -1799,6 +1845,30 @@
"description": "Button that opens the system settings page"
},
"permissionSettingsMessage": "「{what}」이(가) 거부되어 시스템이 다시 묻지 않습니다. 설정에서 허용해 주세요.",
+ "permissionGuideNotification": "시스템 설정에서 알림을 허용해 주세요.",
+ "permissionGuideForegroundLocation": "시스템 설정에서 정확한 위치를 허용해 주세요.",
+ "permissionGuideBackgroundLocation": "「{option}」에서 「항상 허용」을 선택하세요.",
+ "@permissionGuideBackgroundLocation": {
+ "description": "Instruction for background location",
+ "placeholders": {
+ "option": {}
+ }
+ },
+ "permissionGuideBackgroundExecution": "시스템 설정에서 백그라운드 실행을 허용하여 알림이 중지되지 않게 하세요.",
+ "permissionGuideUnusedPause": "앱이 「사용 안 함」으로 표시되면 시스템 설정에서 「허용」을 선택하세요.",
+ "permissionGuideUnusedFreeSpace": "저장 공간 부족으로 일시중지된 경우 캐시를 지우고 다시 여세요.",
+ "permissionGuideUnusedRevoke": "앱 권한이 취소된 경우 시스템 설정에서 다시 허용하세요.",
+ "permissionGuideUnusedPlayProtect": "Play 프로텍트가 앱을 일시중지한 경우 Google Play에서 상태를 확인하세요.",
+ "permissionGuideVendorPower": "「{vendor}」의 절전 설정에서 이 앱을 「제한 없음」으로 설정하세요.",
+ "@permissionGuideVendorPower": {
+ "description": "Instruction for vendor power saving",
+ "placeholders": {
+ "vendor": {}
+ }
+ },
+ "permissionStillRequired": "아직 필요합니다. 설정에서 활성화하세요.",
+ "permissionVerifyManually": "시스템 설정에서 이 권한이 활성화되어 있는지 직접 확인하세요.",
+ "permissionBackgroundLocationOption": "「항상 허용」",
"@permissionSettingsMessage": {
"description": "Explains that the system will not ask again for this permission",
"placeholders": {
@@ -1872,6 +1942,9 @@
},
"moreDumpDiagnostics": "디버그 정보 및 로그 업로드",
"moreDumpDiagnosticsHint": "업로드한 뒤 링크를 복사합니다",
+ "dumpIncludeSensitive": "정확한 위치 포함",
+ "dumpIncludeSensitiveHint": "로그 및 백그라운드 위치의 좌표를 포함합니다. 선택하지 않으면 null로 대체됩니다",
+ "dumpUpload": "업로드",
"dumpUploaded": "업로드됨",
"dumpLinkCopied": "링크를 클립보드에 복사했습니다",
"dumpCopyAgain": "다시 복사",
diff --git a/lib/l10n/app_th.arb b/lib/l10n/app_th.arb
index 82d04c2f4..8f90516ea 100644
--- a/lib/l10n/app_th.arb
+++ b/lib/l10n/app_th.arb
@@ -19,29 +19,29 @@
"reportFilterIntensity": "ความเข้ม",
"mapLayerLightning": "ฟ้าผ่า",
"restroomTypeMale": "ห้องน้ำชาย",
- "meshtasticLastReceived": "Last received",
+ "meshtasticLastReceived": "รับล่าสุด",
"reportDetailSortByCounty": "เรียงตามพื้นที่",
"@moonDays": {
"description": "Day unit for the moon age"
},
"homeRainTrendScattered": "อาจมีฝนตกประปราย",
- "meshtasticUptime": "Uptime",
+ "meshtasticUptime": "เวลาทำงาน",
"weatherRankingTempExtremes": "ค่าสุดขั้วอุณหภูมิ",
"themeLight": "สว่าง",
"mapTerrainReliefHint": "แสดงความนูนของภูมิประเทศบนแผนที่ฐาน",
- "meshtasticEmptyMessage": "(empty message)",
+ "meshtasticEmptyMessage": "(ข้อความว่าง)",
"moreSectionRegion": "พื้นที่",
"mapLayerSatellite": "Himawari Infrared (B13)",
"@meshtasticTapNode": {
"description": "Resting state of the map node sheet"
},
"aedHoursSaturday": "เวลาวันเสาร์",
- "moonPhaseNew": "New moon",
+ "moonPhaseNew": "พระจันทร์ใหม่",
"notifySectionEew": "การเตือนแผ่นดินไหวล่วงหน้า",
"mapResetNorth": "กลับไปทางเหนือ",
"rainInterval2d": "2 วัน",
"mapTownLabelsHint": "แสดงชื่อตำบลเมื่อขยายแผนที่",
- "commonCancel": "Cancel",
+ "commonCancel": "ยกเลิก",
"notifyOptTsunamiWarning": "เฉพาะการเตือนภัยสึนามิ",
"mapLayerSatelliteBtdFog": "Himawari Night Fog",
"@meshtasticSelectDevice": {
@@ -59,7 +59,7 @@
"notifySettingsMenu": "การตั้งค่าการแจ้งเตือน",
"mapAppDefault": "{app} (ค่าเริ่มต้น)",
"trendRange24h": "24 ชม.",
- "mapLayerStyleJmaTooltip": "Grayscale base, tinted below −40 °C to highlight cloud-top height",
+ "mapLayerStyleJmaTooltip": "ฐานเป็น grayscale แต่งสีต่ำกว่า −40 °C เพื่อเน้นความสูงยอดเมฆ",
"mapLayerRain": "ปริมาณฝน",
"mapLayerQpesums": "พยากรณ์ฝน 1 ชั่วโมงข้างหน้า",
"@weatherModeSnow": {
@@ -82,16 +82,16 @@
"changelogShowSnapshots": "แสดงรุ่นทดสอบ",
"changelogTitle": "บันทึกการอัปเดต",
"reportFilterOrderDesc": "มาก→น้อย",
- "meshtasticExcludeMqttSubtitle": "Nodes bridged over the internet, not heard by radio",
+ "meshtasticExcludeMqttSubtitle": "โหนดที่เชื่อมผ่านอินเทอร์เน็ต ไม่ได้ยินผ่านวิทยุ",
"reportFilterIntensityInfoTitle": "มาตรวัดความรุนแรงแบบใหม่/เก่า",
"mapLayerTyphoon": "ไต้ฝุ่น",
"radarOverlayMenuTooltip": "ตัวเลือกชั้นเรดาร์",
"@meshtasticChannelUse": {
"description": "Share of airtime seen busy"
},
- "meshtasticNodes": "Nodes",
- "meshtasticSend": "Send",
- "typhoonOverlayStormL7Tooltip": "Level-7 wind field + average circle (purple)",
+ "meshtasticNodes": "โหนด",
+ "meshtasticSend": "ส่ง",
+ "typhoonOverlayStormL7Tooltip": "สนามลมระดับ 7 + รัศมีเฉลี่ย (ม่วง)",
"aedType": "ประเภท",
"termsOfService": "ข้อกำหนดในการให้บริการ",
"typhoonLegendCircle25": "วงพายุ (รุนแรง)",
@@ -110,12 +110,12 @@
"@meshtasticExcludeMqttSubtitle": {
"description": "What an MQTT node is"
},
- "meshtasticFirmware": "Firmware",
+ "meshtasticFirmware": "เฟิร์มแวร์",
"@mapLayerMeshtastic": {
"description": "Map layer name: mesh nodes"
},
"reportFilterDateEndNote": "วันสิ้นสุด: 24:00 ของวันนั้น(ไทเป)",
- "meshtasticSilent": "Silent",
+ "meshtasticSilent": "เงียบ",
"reportFilterSortMagnitude": "ขนาด",
"mapLayerCategoryEarthquake": "แผ่นดินไหว",
"mapLayerSatelliteB12": "Himawari Ozone (B12)",
@@ -144,12 +144,12 @@
"@radarCountyOutlineHint": {
"description": "Hint under the county-border toggle in the radar overlay menu."
},
- "meshtasticLayerOptions": "Node options",
+ "meshtasticLayerOptions": "ตัวเลือกโหนด",
"onboardingAgreeContinue": "ยอมรับและดำเนินการต่อ",
- "meshtasticNodeId": "Node ID",
+ "meshtasticNodeId": "รหัสโหนด",
"commonRetry": "ลองอีกครั้ง",
"reportDetailNumbered": "แผ่นดินไหวรู้สึกได้อย่างมีนัยสำคัญ หมายเลข {number}",
- "typhoonOverlayStormBandSubtitle": "With average circle",
+ "typhoonOverlayStormBandSubtitle": "พร้อมรัศมีเฉลี่ย",
"disasterMapOverlayRestroomTooltip": "แสดงห้องน้ำสาธารณะ",
"weatherRankingTitle": "อันดับการสังเกต",
"homeRainTrendHeavySustained": "ฝนตกหนักต่อเนื่องตลอดชั่วโมงหน้า",
@@ -161,12 +161,12 @@
"@meshtasticSilent": {
"description": "Legend: node known but not heard recently"
},
- "meshtasticChannelWorking": "Setting up the DPIP channel…",
- "meshtasticRegionSwitch": "Switch to TW",
+ "meshtasticChannelWorking": "กำลังตั้งค่าช่อง DPIP…",
+ "meshtasticRegionSwitch": "สลับเป็นภูมิภาค TW",
"@meshtasticLastReceived": {
"description": "Age of the last received packet"
},
- "meshtasticTraffic": "Traffic",
+ "meshtasticTraffic": "ปริมาณข้อมูล",
"@meshtasticDpipChannel": {
"description": "Which channel DPIP payloads use"
},
@@ -176,8 +176,8 @@
"description": "Moon page title"
},
"mapLayerHumidity": "ความชื้น",
- "mapLayerSatelliteTransparentNight": "Night = transparent, the basemap shows",
- "meshtasticScanning": "Scanning…",
+ "mapLayerSatelliteTransparentNight": "กลางคืน = โปร่งใส เห็นแผนที่ฐาน",
+ "meshtasticScanning": "กำลังสแกน…",
"@meshtasticDevice": {
"description": "Section: device identity"
},
@@ -202,7 +202,7 @@
"meshtasticEtaDays": "~{n} วัน",
"meshtasticTitle": "Meshtastic",
"navMore": "เพิ่มเติม",
- "meshtasticDpipChannel": "DPIP channel",
+ "meshtasticDpipChannel": "ช่อง DPIP",
"disasterMapOverlaySectionLayers": "ชั้น",
"@moonPhaseWaningCrescent": {
"description": "Phase: waning crescent"
@@ -215,15 +215,15 @@
"description": "Label for the weatherModeCloudy option in the experimental backdrop settings."
},
"typhoonLabelNe": "NE",
- "meshtasticCopied": "Message copied",
+ "meshtasticCopied": "คัดลอกข้อความแล้ว",
"reportListEmpty": "ไม่มีรายงานแผ่นดินไหว",
"reportListEnd": "สิ้นสุดรายการ",
"mapLayerSatelliteTruecolor": "Himawari True Color",
- "typhoonOverlaySectionExtra": "Overlays",
+ "typhoonOverlaySectionExtra": "เลเยอร์เสริม",
"eewSWave": "คลื่น S",
- "meshtasticBusyTitle": "Another app is using this radio",
+ "meshtasticBusyTitle": "แอปอื่นกำลังใช้วิทยุเครื่องนี้อยู่",
"restroomCategoryCultural": "สถานที่ทางวัฒนธรรม",
- "typhoonLabelWind": "Max. sustained wind near centre",
+ "typhoonLabelWind": "ลมแรงสุดต่อเนื่องใกล้ศูนย์กลาง",
"radarGlobalOutlineHint": "กรอบนอกของทุกประเทศ",
"notifyEvacuation": "ข้อมูลภัยพิบัติ",
"typhoonLegendCircle15": "วงพายุ (แรง)",
@@ -233,11 +233,11 @@
"@meshtasticRadioSettings": {
"description": "Section: LoRa settings"
},
- "dataSectionAstronomy": "Astronomy",
+ "dataSectionAstronomy": "ดาราศาสตร์",
"homeRainTrendLightSustained": "ฝนตกเล็กน้อยต่อเนื่องตลอดชั่วโมงหน้า",
"commonError": "เกิดข้อผิดพลาด",
- "moonPhaseWaningCrescent": "Waning crescent",
- "meshtasticPower": "Power",
+ "moonPhaseWaningCrescent": "จันทร์เสี้ยวข้างแรม",
+ "meshtasticPower": "พลังงาน",
"@meshtasticChannelWorking": {
"description": "Creating/verifying the DPIP channel"
},
@@ -248,14 +248,14 @@
"typhoonWarningAreas": "พื้นที่: {areas}",
"rainIntervalSection": "ช่วงเวลา",
"notifyTitle": "การแจ้งเตือน",
- "meshtasticTxPower": "TX power",
+ "meshtasticTxPower": "กำลัง TX",
"@radarTownOutlineHint": {
"description": "Hint under the township-border toggle in the radar overlay menu."
},
"restroomCategoryLabel": "หมวดหมู่",
"sponsorRestoring": "กำลังกู้คืนการซื้อ…",
"sponsorIntro": "DPIP มุ่งมั่นให้ข้อมูลการป้องกันภัยพิบัติแบบเรียลไทม์ โดยไม่มีโฆษณาหรือรูปแบบหารายได้อื่น การสนับสนุนของคุณช่วยให้เรารักษาเซิร์ฟเวอร์และพัฒนาต่อไปได้",
- "typhoonLabelStormAvg": "Avg. radius of Beaufort 10 winds",
+ "typhoonLabelStormAvg": "รัศมีเฉลี่ยลมโบฟอร์ต 10",
"@meshtasticHardware": {
"description": "Board model"
},
@@ -274,8 +274,8 @@
"rainInterval6h": "6 ชม.",
"homeRainTrendMinute": "{minute} นาที",
"restroomTypeUnspecified": "ไม่ระบุ",
- "typhoonOverlayProbabilityHint": "Hides the forecast cone",
- "mapLayerSatelliteGlobalOutline": "Country border",
+ "typhoonOverlayProbabilityHint": "ซ่อนกรวยคาดการณ์",
+ "mapLayerSatelliteGlobalOutline": "เส้นขอบประเทศ",
"mapNavTemperature": "อุณหภูมิ",
"typhoonLegendForecastPoint": "จุดพยากรณ์",
"@meshtasticBattery": {
@@ -289,16 +289,16 @@
"rainInterval3d": "3 วัน",
"defaultMapLayerSubtitle": "แท็บแผนที่จะเปิดชั้นนี้ ไอคอนและป้ายนำทางด้านล่างจะเปลี่ยนตาม",
"aedDescription": "หมายเหตุ",
- "typhoonOverlayWeatherRadarTooltip": "Radar echo closest to the typhoon bulletin time",
+ "typhoonOverlayWeatherRadarTooltip": "เรดาร์สะท้อนที่ใกล้เวลารายงานพายุไต้ฝุ่นที่สุด",
"onboardingPermLocationDesc": "ส่งการเตือนภัยตามตำแหน่งที่คุณอยู่",
"mapLayerSatelliteB16": "Himawari CO₂ (B16)",
"@meshtasticClearMessages": {
"description": "Menu action clearing the message log"
},
"homeActiveEventsEmpty": "ไม่มีเหตุการณ์ที่ยังมีผล",
- "typhoonLabelPosition": "Centre location",
+ "typhoonLabelPosition": "ตำแหน่งศูนย์กลาง",
"weatherRankingBy": "เรียง",
- "typhoonIntensityMild": "Mild typhoon",
+ "typhoonIntensityMild": "พายุไต้ฝุ่นอ่อน",
"windForecastGlobalOutlineHint": "กรอบนอกของทุกประเทศ",
"rainInterval1h": "1 ชม.",
"eewLocalIntensity": "ประมาณ ณ ตำแหน่ง",
@@ -307,23 +307,23 @@
"description": "Radar scan-range overlay toggle in the map's radar overlay menu."
},
"restroomCategoryReligious": "สถานที่ทางศาสนา",
- "meshtasticRole": "Role",
- "mapLayerSatelliteCloudCloudy": "Cloudy",
+ "meshtasticRole": "บทบาท",
+ "mapLayerSatelliteCloudCloudy": "มีเมฆ",
"skyTimeSunrise": "พระอาทิตย์ขึ้น",
"@mapLayerMeshtasticSubtitle": {
"description": "Map layer switcher subtitle"
},
"meshtasticJumpToLatest": "ไปที่ล่าสุด",
- "meshtasticNoMessages": "No messages yet",
+ "meshtasticNoMessages": "ยังไม่มีข้อความ",
"onboardingPermNotifyDesc": "ส่งการเตือนแผ่นดินไหว สภาพอากาศ และภัยพิบัติทันทีที่เกิดขึ้น",
"radarTownOutline": "เส้นแบ่งเขตอำเภอ",
- "mapLayerStyleSection": "Colour style",
+ "mapLayerStyleSection": "สไตล์สี",
"@moonPhaseNew": {
"description": "Phase: new moon"
},
"disasterMapOverlayMenuTooltip": "ชั้นแผนที่ป้องกันภัย",
"moreGooglePlay": "Google Play",
- "meshtasticOnline": "Heard recently",
+ "meshtasticOnline": "เพิ่งได้ยิน",
"@meshtasticSendHint": {
"description": "Message input hint"
},
@@ -331,7 +331,7 @@
"typhoonForecastLead": "Forecast +{hours} h",
"@mapAppOpenFailed": {},
"changelogTypeStable": "ทางการ",
- "mapLayerSatelliteTransparentClear": "Clear sky = transparent, the basemap shows",
+ "mapLayerSatelliteTransparentClear": "ท้องฟ้าใส = โปร่งใส เห็นแผนที่ฐาน",
"@skyTimeAuto": {
"description": "Label for the skyTimeAuto option in the experimental backdrop settings."
},
@@ -350,11 +350,11 @@
"mapLayerSatelliteTransparentNoVegetation": "Below 0.1 = transparent (no vegetation)",
"notifyOptLocalIntensity4": "ความรุนแรงในพื้นที่ระดับ 4 ขึ้นไป",
"eewArrived": "มาถึงแล้ว",
- "meshtasticNoDevices": "No Meshtastic devices found",
+ "meshtasticNoDevices": "ไม่พบอุปกรณ์ Meshtastic",
"mapLayerCategoryLife": "ชีวิตประจำวัน",
"reportFilterSortIntensity": "ความเข้ม",
- "meshtasticStateDisconnected": "Disconnected",
- "typhoonIntensityIntense": "Intense typhoon",
+ "meshtasticStateDisconnected": "ตัดการเชื่อมต่อแล้ว",
+ "typhoonIntensityIntense": "พายุไต้ฝุ่นรุนแรง",
"@meshtasticSend": {
"description": "Send message button"
},
@@ -366,7 +366,7 @@
"description": "The radio's short name"
},
"dpmYes": "ใช่",
- "meshtasticNoHistory": "Not enough history yet",
+ "meshtasticNoHistory": "ประวัติยังไม่พอ",
"reportDetailLocalIntensityUnavailable": "ไม่มีข้อมูลความเข้ม",
"mapLayerWindForecastGfs": "GFS",
"reportFilterDepth": "ความลึก",
@@ -390,8 +390,8 @@
},
"reportFilterReset": "รีเซ็ต",
"mapLayerSatelliteMndwi": "Himawari MNDWI",
- "typhoonOverlaySectionStorm": "Storm wind",
- "moonPhaseFull": "Full moon",
+ "typhoonOverlaySectionStorm": "ลมพายุ",
+ "moonPhaseFull": "พระจันทร์เต็มดวง",
"@meshtasticEmptyMessage": {
"description": "Placeholder for a text packet with no body"
},
@@ -399,24 +399,24 @@
"@radarGlobalOutlineHint": {
"description": "Hint under the national-border toggle in the radar overlay menu."
},
- "moonPhaseWaningGibbous": "Waning gibbous",
+ "moonPhaseWaningGibbous": "จันทร์นูนข้างแรม",
"reportFilterIntensityInfoModernTitle": "แบบใหม่ (ตั้งแต่ 2020)",
"@mapAppGoogleMaps": {},
- "typhoonDataTime": "Data time\n{time}",
+ "typhoonDataTime": "เวลาข้อมูล\n{time}",
"restroomTypeAccessible": "ห้องน้ำคนพิการ",
"moreSectionAbout": "เกี่ยวกับ",
- "meshtasticSelectDevice": "Select a radio",
+ "meshtasticSelectDevice": "เลือกวิทยุ",
"onboardingIntroBody": "DPIP คือเพื่อนคู่ใจด้านการป้องกันภัยพิบัติของคุณ รวมการเตือนแผ่นดินไหวล่วงหน้า รายงานแผ่นดินไหว สภาพอากาศ และข้อมูลภัยพิบัติต่าง ๆ ไว้ในที่เดียว และแจ้งเตือนคุณในช่วงเวลาสำคัญ\n\n• แผ่นดินไหว: การเตือนล่วงหน้า รายงานความรุนแรง และรายงานฉบับสมบูรณ์\n• สภาพอากาศ: ข้อความพายุฝนฟ้าคะนองแบบเรียลไทม์ และการแจ้งเตือนสภาพอากาศ\n• ข้อมูลสึนามิและภัยพิบัติ\n\nต่อไป เราจะขอให้คุณอ่านข้อกำหนดการให้บริการ และอนุญาตสิทธิ์บางอย่างเพื่อให้ DPIP สามารถปกป้องคุณได้แบบเรียลไทม์",
"shelterCapacityLabel": "ความจุ",
"reportDetailImage": "ภาพรายงานแผ่นดินไหว",
- "meshtasticStateConfiguring": "Configuring…",
+ "meshtasticStateConfiguring": "กำลังกำหนดค่า…",
"@moonPhaseLastQuarter": {
"description": "Phase: last quarter"
},
- "typhoonLabelGaleAvg": "Avg. radius of Beaufort 7 winds",
+ "typhoonLabelGaleAvg": "รัศมีเฉลี่ยลมโบฟอร์ต 7",
"onboardingPermNotify": "การแจ้งเตือน",
- "meshtasticClearMessages": "Clear messages",
- "meshtasticNotifyMessages": "Notify on new messages",
+ "meshtasticClearMessages": "ล้างข้อความ",
+ "meshtasticNotifyMessages": "แจ้งเตือนข้อความใหม่",
"defaultMapLayerSettings": "ชั้นแผนที่เริ่มต้น",
"eewSourceSettings": "แหล่งที่มาของ EEW",
"eewSourceSubtitle": "เลือกหน่วยงานที่ต้องการแสดงการแจ้งเตือนแผ่นดินไหวล่วงหน้า",
@@ -446,7 +446,7 @@
"description": "Label for the skyTimeAfternoon option in the experimental backdrop settings."
},
"mapTimelineFuture": "อนาคต",
- "typhoonLegendCircleAvg": "Average circle",
+ "typhoonLegendCircleAvg": "รัศมีเฉลี่ย",
"reportFilterDepthKm": "{depth} km",
"typhoonLabelSe": "SE",
"radarTownOutlineHint": "เส้นแบ่งย่อยกว่า",
@@ -454,7 +454,7 @@
"@meshtasticDisconnect": {
"description": "Disconnect from the radio"
},
- "typhoonLabelGust": "Peak gust",
+ "typhoonLabelGust": "ลมกระโชกสูงสุด",
"mapAppGoogleMaps": "Google Maps",
"sponsorTerms": "ข้อกำหนดการใช้งาน",
"restroomTypeGenderNeutral": "ห้องน้ำเป็นกลางทางเพศ",
@@ -463,7 +463,7 @@
},
"notifyThunderstorm": "การแจ้งเตือนพายุฝนฟ้าคะนอง",
"skyTimeGolden": "ช่วงเวลาทอง",
- "moonAge": "Age",
+ "moonAge": "อายุจันทร์",
"@windForecastTownOutlineHint": {
"description": "Hint under the township-border toggle in the wind-forecast overlay menu."
},
@@ -474,20 +474,20 @@
"moreGithub": "ExpTech GitHub",
"homeForecastUnavailable": "เลือกพื้นที่เพื่อดูพยากรณ์",
"mapLayers": "ชั้นข้อมูล",
- "meshtasticHardware": "Hardware",
+ "meshtasticHardware": "ฮาร์ดแวร์",
"languageSettings": "ภาษา",
"@moonNextFullMoon": {
"description": "Next full moon date label"
},
"language": "ภาษา",
"homeForecastFeelsLike": "รู้สึกเหมือน {temp}°",
- "typhoonOverlayWeatherHint": "Aligned to bulletin time",
+ "typhoonOverlayWeatherHint": "จัดให้ตรงเวลารายงาน",
"@meshtasticHopLimit": {
"description": "How many hops a packet may take"
},
"skyTimeDawn": "รุ่งอรุณ",
"skyTimeAfternoon": "ตอนบ่าย",
- "meshtasticLastHeard": "Last heard",
+ "meshtasticLastHeard": "ได้ยินล่าสุด",
"typhoonWarningTitle": "ประกาศเตือนไต้ฝุ่น",
"moreSourceCode": "ซอร์สโค้ด",
"mapLayerCategoryWeather": "การสังเกตสภาพอากาศ",
@@ -506,37 +506,37 @@
"mapTimelineForecast": "พยากรณ์",
"restroomTypeLabel": "ประเภท",
"navEarthquake": "แผ่นดินไหว",
- "typhoonOverlayStormL10Tooltip": "Level-10 wind field + average circle (yellow)",
- "moonPhaseWaxingGibbous": "Waxing gibbous",
+ "typhoonOverlayStormL10Tooltip": "สนามลมระดับ 10 + รัศมีเฉลี่ย (เหลือง)",
+ "moonPhaseWaxingGibbous": "จันทร์นูนข้างขึ้น",
"reportDetailTitle": "รายงานแผ่นดินไหว",
"moreTremReport": "รายงานการตรวจจับ TREM",
"weatherDataTime": "{station} · เวลาข้อมูล {time}",
- "meshtasticNoNodes": "No nodes heard yet",
- "meshtasticViaMqtt": "Via MQTT (internet)",
+ "meshtasticNoNodes": "ยังไม่พบโหนด",
+ "meshtasticViaMqtt": "ผ่าน MQTT (อินเทอร์เน็ต)",
"radarCountyOutline": "เส้นแบ่งเขตจังหวัด",
"@mapAppCopyCoordinates": {},
"commonClose": "ปิด",
"restroomGradeLabel": "ระดับ",
"rainIntervalNow": "วันนี้",
"changelogCurrentVersion": "ปัจจุบัน",
- "typhoonOverlayForecastCalloutsTooltip": "Show forecast-point detail cards when zoomed in",
- "typhoonLabelPressure": "Central pressure",
+ "typhoonOverlayForecastCalloutsTooltip": "แสดงการ์ดรายละเอียดจุดคาดการณ์เมื่อซูมเข้า",
+ "typhoonLabelPressure": "ความกดอากาศศูนย์กลาง",
"aedOpenRemark": "หมายเหตุเวลาเปิด",
"onboardingPermsBody": "เพื่อให้ DPIP แจ้งเตือนคุณได้ในทันทีที่เกิดภัยพิบัติ โปรดอนุญาตสิทธิ์ต่อไปนี้ คุณสามารถเปลี่ยนแปลงได้ทุกเมื่อในการตั้งค่าระบบ",
- "typhoonOverlaySectionWeather": "Weather underlay",
+ "typhoonOverlaySectionWeather": "พื้นหลังสภาพอากาศ",
"@meshtasticStateConnected": {
"description": "Connection state label"
},
"notifyOptWeatherLocal": "เฉพาะตำแหน่งปัจจุบัน",
"mapNavRain": "ฝน",
- "moonDays": "days",
+ "moonDays": "วัน",
"mapLegendUnit": "หน่วย: {unit}",
"weatherModeClear": "ท้องฟ้าแจ่มใส",
- "meshtasticRadio": "Radio",
+ "meshtasticRadio": "วิทยุ",
"commonEmpty": "ไม่มีข้อมูล",
"mapLayerSatelliteB01": "Himawari Blue (B01)",
- "meshtasticExternalPower": "External power",
- "moonPhaseLastQuarter": "Last quarter",
+ "meshtasticExternalPower": "พลังงานภายนอก",
+ "moonPhaseLastQuarter": "จันทร์กึ่งดวงข้างแรม",
"@meshtasticName": {
"description": "The radio's long name"
},
@@ -551,20 +551,20 @@
"mapLayerRestroom": "ห้องน้ำสาธารณะ",
"restroomCategoryWelfare": "สถานสงเคราะห์",
"restroomGradeExcellent": "ดีเยี่ยม",
- "meshtasticLastSent": "Last sent",
- "meshtasticName": "Name",
- "meshtasticScan": "Scan",
+ "meshtasticLastSent": "ส่งล่าสุด",
+ "meshtasticName": "ชื่อ",
+ "meshtasticScan": "สแกน",
"@radarOverlayMenuTooltip": {
"description": "Tooltip for the radar overlay-options chip beside the layer switcher"
},
"mapLayerCategoryForecast": "การพยากรณ์เชิงตัวเลข",
- "meshtasticChannelFailed": "Couldn't set up the DPIP channel",
+ "meshtasticChannelFailed": "ตั้งค่าช่อง DPIP ไม่สำเร็จ",
"themeSystem": "ระบบ",
"mapLayerSatelliteNdvi": "Himawari NDVI",
"typhoonLegendForecast": "เส้นทางพยากรณ์",
"typhoonValueHpa": "{n} hPa",
"weatherPrecipitation": "ปริมาณน้ำฝน",
- "moonNextFullMoon": "Next full moon",
+ "moonNextFullMoon": "พระจันทร์เต็มดวงครั้งถัดไป",
"dpmSheetEmpty": "แตะเครื่องหมายบนแผนที่เพื่อดูรายละเอียด",
"onboardingSkipLeave": "ข้ามไปก่อน",
"aedPlaceDesc": "ตำแหน่งติดตั้ง",
@@ -582,22 +582,22 @@
},
"onboardingPermBattery": "ยกเว้นการประหยัดแบตเตอรี่",
"typhoonLabelNw": "NW",
- "moonPhaseWaxingCrescent": "Waxing crescent",
+ "moonPhaseWaxingCrescent": "จันทร์เสี้ยวข้างขึ้น",
"restroomCategoryLeisure": "สถานที่พักผ่อนหย่อนใจ",
"mapLayerTemperature": "อุณหภูมิ",
"aedCategory": "หมวดหมู่",
"@moonTimelineCaption": {
"description": "Moon phase timeline caption"
},
- "meshtasticChannels": "Channels",
+ "meshtasticChannels": "ช่อง",
"monitorWaiting": "กำลังรอข้อมูล…",
- "typhoonOverlayForecastCallouts": "Forecast tooltips",
+ "typhoonOverlayForecastCallouts": "คำอธิบายจุดคาดการณ์",
"@meshtasticTitle": {
"description": "Meshtastic test page title"
},
"reportDetailEpicenter": "พิกัดศูนย์กลาง",
- "meshtasticVoltage": "Voltage",
- "mapLayerMeshtasticSubtitle": "LoRa mesh nodes heard by your radio",
+ "meshtasticVoltage": "แรงดันไฟฟ้า",
+ "mapLayerMeshtasticSubtitle": "โหนดเมช LoRa ที่วิทยุได้ยิน",
"@meshtasticSent": {
"description": "Packets sent this session"
},
@@ -623,34 +623,34 @@
"description": "Township-border overlay toggle in the map's radar overlay menu."
},
"mapLayerSatelliteB04": "Himawari Near-Infrared (B04)",
- "mapLayerSatelliteTransparentZero": "Zero difference = transparent (no signal)",
+ "mapLayerSatelliteTransparentZero": "ค่าต่างเป็นศูนย์ = โปร่งใส (ไม่มีสัญญาณ)",
"shelterIndoorLabel": "การอพยพในอาคาร",
"notifyOptOff": "ปิด",
"reportFilterSortTime": "เวลา",
- "mapLayerSatelliteCloudProbablyClear": "Probably clear",
+ "mapLayerSatelliteCloudProbablyClear": "น่าจะปลอดโปร่ง",
"weatherModeThunderstorm": "พายุฝนฟ้าคะนอง",
"homeViewOnMap": "ดูบนแผนที่",
"reportFilterIntensityInfoLegacyTitle": "แบบเก่า (ก่อน 2020)",
- "typhoonLabelSpeed": "Past movement speed",
+ "typhoonLabelSpeed": "ความเร็วเคลื่อนที่",
"@meshtasticReconnecting": {
"description": "The link dropped and is being re-established"
},
"mapAppOpenFailed": "ไม่สามารถเปิด {app} ได้",
- "mapLayerSatelliteRgbComposite": "RGB composite (JMA recipe)",
+ "mapLayerSatelliteRgbComposite": "RGB composite (สูตร JMA)",
"@meshtasticStateDisconnected": {
"description": "Connection state label"
},
- "meshtasticReceived": "Received",
+ "meshtasticReceived": "รับแล้ว",
"weatherRankingExtremeLow": "ต่ำสุดวันนี้",
"@meshtasticRegionSwitch": {
"description": "Button applying the DPIP LoRa region"
},
"mapLayerSatelliteB10": "Himawari Lower Water Vapour (B10)",
- "mapLayerSatelliteCloudProbablyCloudy": "Probably cloudy",
+ "mapLayerSatelliteCloudProbablyCloudy": "น่าจะมีเมฆ",
"shelterCategoryLabel": "ประเภทภัยพิบัติ",
"mapLayerSatelliteTransparentNoWater": "≤ 0 = transparent (no water)",
- "meshtasticStateConnecting": "Connecting…",
- "moonTitle": "Moon",
+ "meshtasticStateConnecting": "กำลังเชื่อมต่อ…",
+ "moonTitle": "ดวงจันทร์",
"weatherRankingGust": "ลมกระโชก",
"moreAppStore": "App Store",
"@meshtasticUndecoded": {
@@ -661,7 +661,7 @@
},
"moreServerStatus": "สถานะเซิร์ฟเวอร์",
"notifySectionWeather": "สภาพอากาศ",
- "meshtasticPreset": "Modem preset",
+ "meshtasticPreset": "โหมดโมเด็ม",
"dataSectionSeismic": "แผ่นดินไหว",
"changelogBodyEmpty": "ไม่มีคำอธิบายสำหรับรุ่นนี้",
"changelogOpenOnGitHub": "ดูบน GitHub",
@@ -670,15 +670,15 @@
"regionNationwide": "ทั่วประเทศ",
"moreNotifyLog": "บันทึกการส่งการแจ้งเตือนของ DPIP",
"regionCurrent": "ตำแหน่งปัจจุบัน",
- "meshtasticNotConnected": "Not connected to a radio",
+ "meshtasticNotConnected": "ยังไม่ได้เชื่อมต่อกับวิทยุ",
"weatherModeSnow": "หิมะตก",
- "mapLayerMeshtastic": "Meshtastic nodes",
+ "mapLayerMeshtastic": "โหนด Meshtastic",
"moreDeveloper": "ข้อมูลดีบัก",
"@qpesumsOverlayMenuTooltip": {
"description": "Tooltip for the QPESUMS forecast overlay-options chip beside the layer switcher."
},
"mapLayerSatelliteB14": "Himawari Longwave Infrared (B14)",
- "meshtasticChannelUse": "Channel use",
+ "meshtasticChannelUse": "การใช้ช่อง",
"mapNavLightning": "ฟ้าผ่า",
"homeForecastEmpty": "ไม่มีข้อมูลพยากรณ์",
"sponsorOneTime": "สนับสนุนครั้งเดียว",
@@ -686,7 +686,7 @@
"onboardingPermBackground": "ตำแหน่งที่ตั้งเบื้องหลัง",
"aedEmergencyPhone": "โทรศัพท์ฉุกเฉิน",
"dpmOpenInMaps": "เปิดในแผนที่",
- "meshtasticNotifyNodes": "Notify on new nodes",
+ "meshtasticNotifyNodes": "แจ้งเตือนโหนดใหม่",
"onboardingPermCriticalDesc": "ให้การเตือนแผ่นดินไหวที่เป็นอันตรายถึงชีวิตส่งเสียงได้ แม้อยู่ในโหมดเงียบหรือโหมดห้ามรบกวน",
"@mapAppDefault": {
"placeholders": {
@@ -695,11 +695,11 @@
}
}
},
- "mapLayerSatelliteTransparentWarm": "Clear sky (warm end) = transparent, the basemap shows",
- "meshtasticSent": "Sent",
+ "mapLayerSatelliteTransparentWarm": "ท้องฟ้าใส (ปลายอุ่น) = โปร่งใส เห็นแผนที่ฐาน",
+ "meshtasticSent": "ส่งแล้ว",
"homeForecastTitle": "พยากรณ์ 24 ชั่วโมง",
"typhoonLegendWarningAreas": "พื้นที่เตือนภัย",
- "meshtasticExcludeMqttHidden": "{count} hidden",
+ "meshtasticExcludeMqttHidden": "ซ่อน {count} รายการ",
"notifyOptLocalIntensity1": "ความรุนแรงในพื้นที่ระดับ 1 ขึ้นไป",
"@skyTimeGolden": {
"description": "Label for the skyTimeGolden option in the experimental backdrop settings."
@@ -710,21 +710,21 @@
"mapTimelinePast": "อดีต",
"restroomTypeFemale": "ห้องน้ำหญิง",
"reportListToday": "วันนี้",
- "meshtasticTapNode": "Tap a node for details",
+ "meshtasticTapNode": "แตะโหนดเพื่อดูรายละเอียด",
"commonLoading": "กำลังโหลด…",
"@meshtasticStateConnecting": {
"description": "Connection state label"
},
- "typhoonIntensityModerate": "Moderate typhoon",
+ "typhoonIntensityModerate": "พายุไต้ฝุ่นปานกลาง",
"mapLayerSatelliteAsh": "Himawari Ash",
"rainInterval3h": "3 ชม.",
- "meshtasticChannelReady": "DPIP channel ready",
+ "meshtasticChannelReady": "ช่อง DPIP พร้อมแล้ว",
"@meshtasticNotifyNodes": {
"description": "Toggle: local notification when a new node is heard"
},
"mapLayerCategorySatellite": "ดาวเทียม",
"mapLayerSatelliteNightmicrophysics": "Himawari Night Microphysics",
- "typhoonIntensityTd": "Tropical depression",
+ "typhoonIntensityTd": "ดีเปรสชันเขตร้อน",
"reportFilterDate": "วันที่",
"sponsorRestoreUnavailable": "ไม่สามารถเชื่อมต่อร้านค้าได้ โปรดลองอีกครั้งภายหลัง",
"homeForecastPop": "{pop}%",
@@ -773,13 +773,13 @@
}
},
"mapLayerSatelliteBtdSo2": "Himawari SO₂ / Cloud Phase",
- "meshtasticStateError": "Error",
+ "meshtasticStateError": "ข้อผิดพลาด",
"weatherModeOvercast": "ฟ้าปิด",
"@meshtasticScan": {
"description": "Start scanning for Meshtastic radios"
},
"reportDetailDepth": "ความลึกจุดศูนย์กลาง",
- "typhoonOverlayWarningTooltip": "Highlight counties under a typhoon warning",
+ "typhoonOverlayWarningTooltip": "ไฮไลต์จังหวัดที่อยู่ใต้คำเตือนพายุไต้ฝุ่น",
"reportFilterDatePick": "เลือกวันที่",
"onboardingSkipStay": "กลับไปให้สิทธิ์",
"@moonPhaseWaxingCrescent": {
@@ -793,16 +793,16 @@
"description": "Transmit power"
},
"shelterOutdoorLabel": "การอพยพกลางแจ้ง",
- "meshtasticStateConnected": "Connected",
+ "meshtasticStateConnected": "เชื่อมต่อแล้ว",
"mapNavRadar": "เรดาร์",
- "mapLayerSatelliteCloudClear": "Clear",
+ "mapLayerSatelliteCloudClear": "ปลอดโปร่ง",
"eewSummary": "ขนาด {magnitude} · ความลึก {depth} กม.",
"locationBannerPermission": "ยังไม่ได้อนุญาตสิทธิ์ตำแหน่งที่ตั้ง — ไม่สามารถส่งการเตือนภัยเฉพาะพื้นที่ของคุณได้",
- "typhoonOverlayWeatherNoneTooltip": "No radar or infrared underlay",
+ "typhoonOverlayWeatherNoneTooltip": "ไม่มีพื้นหลังเรดาร์หรืออินฟราเรด",
"radarCountyOutlineHint": "วาดทับภาพเอคโค",
"windForecastCountyOutlineHint": "วาดทับบนสนามลม",
"homeRainTrendTitle": "ฝนชั่วโมงถัดไป",
- "moonPhaseFirstQuarter": "First quarter",
+ "moonPhaseFirstQuarter": "จันทร์กึ่งดวงข้างขึ้น",
"mapLayerCategoryTyphoon": "พายุไต้ฝุ่น",
"@windForecastOverlayMenuTooltip": {
"description": "Tooltip for the wind-forecast overlay-options chip beside the layer switcher."
@@ -810,13 +810,13 @@
"@meshtasticNodeId": {
"description": "The radio's node number"
},
- "meshtasticUtilization": "Airtime (24h)",
+ "meshtasticUtilization": "เวลาออกอากาศ (24 ชม.)",
"restroomTypeMixed": "ห้องน้ำรวม",
"restroomGradeGood": "ดี",
"notifyTsunami": "ข้อมูลสึนามิ",
"navData": "ข้อมูล",
"mapLayerSatelliteBtdWvirw": "Himawari Overshooting Top",
- "meshtasticReadingAge": "Reading taken",
+ "meshtasticReadingAge": "เวลาวัดค่า",
"@moonPhaseWaningGibbous": {
"description": "Phase: waning gibbous"
},
@@ -829,7 +829,7 @@
"notifyIntensity": "รายงานความรุนแรงแผ่นดินไหว",
"rainIntervalMenu": "ช่วงสะสม",
"reportDetailLocalFelt": "แผ่นดินไหวรู้สึกได้เฉพาะพื้นที่",
- "meshtasticDevice": "Device",
+ "meshtasticDevice": "อุปกรณ์",
"onboardingGrant": "อนุญาต",
"weatherModeRain": "ฝนตก",
"shelterVulnerableOkLabel": "เหมาะกับผู้เปราะบาง",
@@ -853,7 +853,7 @@
"trendCumulativeTotal": "สะสม {total} มม.",
"languageName": "ไทย",
"reportListEmptyFiltered": "ไม่มีรายงานที่ตรงกับเงื่อนไข",
- "meshtasticExcludeMqtt": "Hide MQTT nodes",
+ "meshtasticExcludeMqtt": "ซ่อนโหนด MQTT",
"mapNavTyphoon": "ไต้ฝุ่น",
"weatherModeSand": "ฝุ่นทราย",
"@moonPhaseFirstQuarter": {
@@ -869,9 +869,9 @@
"feedStale": "ข้อมูลอาจล้าสมัย",
"homeForecastWind": "{direction} · แรง {level}",
"navHome": "หน้าแรก",
- "meshtasticRegionLabel": "Region",
+ "meshtasticRegionLabel": "ภูมิภาค",
"mapLayerSatelliteCloudtop": "Himawari Cloud Top Temperature",
- "moonTimelineCaption": "Phase",
+ "moonTimelineCaption": "ข้างขึ้นข้างแรม",
"@meshtasticChannelNoSlot": {
"description": "Every secondary channel slot is taken"
},
@@ -886,7 +886,7 @@
"reportFilterSortDepth": "ความลึก",
"mapTimelineDataTime": "เวลาข้อมูล {time}",
"radarScanRange": "แสดงขอบเขตการสแกน",
- "meshtasticHopLimit": "Hop limit",
+ "meshtasticHopLimit": "จำนวนฮอปสูงสุด",
"@meshtasticUptime": {
"description": "Time since the radio booted"
},
@@ -897,17 +897,17 @@
"sponsorPrivacy": "นโยบายความเป็นส่วนตัว",
"reportDetailLocalIntensity": "ความเข้มที่ตำแหน่งของคุณ",
"mapLayerSatelliteNaturalcolor": "Himawari Natural Color",
- "meshtasticAirtime": "Air time (TX)",
+ "meshtasticAirtime": "เวลาออกอากาศ (TX)",
"shelterCapacityValue": "{n} คน",
"lightningLegendCc": "เมฆสู่เมฆ · {minutes} นาที",
- "meshtasticSendHint": "Message to broadcast",
+ "meshtasticSendHint": "ข้อความที่จะส่ง",
"monitorDelay": "หน่วงเวลา {value} s",
"@meshtasticFirmware": {
"description": "Firmware version"
},
"dpmNo": "ไม่ใช่",
"mapLayerSatelliteB08": "Himawari Upper Water Vapour (B08)",
- "meshtasticReconnecting": "Reconnecting…",
+ "meshtasticReconnecting": "กำลังเชื่อมต่อใหม่…",
"@mapAppAppleMaps": {},
"@meshtasticReadingAge": {
"description": "How old the battery/airtime numbers are"
@@ -916,16 +916,16 @@
"@moonPhaseWaxingGibbous": {
"description": "Phase: waxing gibbous"
},
- "typhoonOverlayWeatherSatelliteTooltip": "Infrared closest to the typhoon bulletin time",
+ "typhoonOverlayWeatherSatelliteTooltip": "อินฟราเรดที่ใกล้เวลารายงานพายุไต้ฝุ่นที่สุด",
"radarScanRangeHint": "นอกกรอบคือไม่ได้ตรวจวัด",
- "typhoonPickerTd": "Tropical depression TD {no}",
+ "typhoonPickerTd": "ดีเปรสชันเขตร้อน TD {no}",
"mapLayerSatelliteWatervapor": "Himawari Water Vapour",
"regionAddButton": "เพิ่มพื้นที่",
"displaySettings": "การแสดงผล",
"restroomGradePoor": "ต่ำกว่ามาตรฐาน",
"restroomCategoryTourist": "แหล่งท่องเที่ยว",
"locationBannerServiceOff": "บริการระบุตำแหน่งถูกปิด — ไม่สามารถส่งการเตือนภัยเฉพาะพื้นที่ของคุณได้",
- "mapLayerStyleTooltip": "Colour style",
+ "mapLayerStyleTooltip": "สไตล์สี",
"lightningLegendCg": "เมฆสู่พื้น · {minutes} นาที",
"skyTimeAuto": "อัตโนมัติ",
"appLogs": "บันทึกแอป",
@@ -966,21 +966,21 @@
"endpointStateUnknown": "ไม่ทราบ",
"endpointServiceEew": "EEW",
"endpointServiceRts": "RTS",
- "endpointServiceRadar": "Radar",
- "endpointServiceSatellite": "Satellite",
+ "endpointServiceRadar": "เรดาร์",
+ "endpointServiceSatellite": "ดาวเทียม",
"endpointServiceQpesums": "QPE",
- "endpointServiceWind": "Wind",
- "endpointServiceDpm": "Disaster points",
- "endpointServiceWeather": "Weather",
- "endpointServiceRain": "Rain",
- "endpointServiceLightning": "Lightning",
- "endpointServiceTyphoon": "Typhoon",
- "endpointServiceReport": "EQ reports",
- "endpointServiceTremStation": "Tremor station",
- "endpointServiceEvent": "Events",
- "endpointServiceLocation": "Location",
- "endpointServiceNotify": "Notifications",
- "endpointServiceOther": "Other",
+ "endpointServiceWind": "ลม",
+ "endpointServiceDpm": "จุดภัยพิบัติ",
+ "endpointServiceWeather": "สภาพอากาศ",
+ "endpointServiceRain": "ฝน",
+ "endpointServiceLightning": "ฟ้าผ่า",
+ "endpointServiceTyphoon": "พายุไต้ฝุ่น",
+ "endpointServiceReport": "รายงานแผ่นดินไหว",
+ "endpointServiceTremStation": "สถานีวัดแรงสั่นสะเทือน",
+ "endpointServiceEvent": "เหตุการณ์",
+ "endpointServiceLocation": "ตำแหน่ง",
+ "endpointServiceNotify": "การแจ้งเตือน",
+ "endpointServiceOther": "อื่น ๆ",
"feedConnecting": "กำลังเชื่อมต่อ…",
"notifyBannerDisabled": "ปิดการแจ้งเตือนอยู่ — คุณจะไม่ได้รับการเตือนภัยพิบัติ",
"@meshtasticNoNodes": {
@@ -989,27 +989,28 @@
"weatherHumidity": "ความชื้น",
"typhoonValueMs": "{n} m/s",
"homeForecastHumidity": "ความชื้น {value}%",
- "meshtasticBusyBody": "Disconnect it in the other Meshtastic app first. Two apps on one radio take each other's messages, so some will go missing.",
- "meshtasticChannelNoSlot": "No free channel slot — free one on the radio",
+ "meshtasticBusyBody": "ตัดการเชื่อมต่อวิทยุในแอป Meshtastic อื่นก่อน วิทยุเครื่องเดียวที่ใช้สองแอปจะแย่งข้อความกัน บางข้อความอาจหายไป",
+ "meshtasticChannelNoSlot": "ไม่มีช่องว่าง — ปล่อยช่องหนึ่งบนวิทยุ",
"restroomCategoryTransport": "การคมนาคม",
- "meshtasticBattery": "Battery",
+ "meshtasticBattery": "แบตเตอรี่",
"meshtasticDistance": "ระยะทาง",
"meshtasticSnrTrend": "แนวโน้มสัญญาณ (SNR)",
"meshtasticBatteryTrend": "แนวโน้มแบตเตอรี่",
- "typhoonOverlayMenuTooltip": "Typhoon overlay options",
+ "typhoonOverlayMenuTooltip": "ตัวเลือกเลเยอร์พายุไต้ฝุ่น",
"mapLayerSatelliteBtdOzone": "Himawari Tropopause",
- "meshtasticRegionMismatch": "Radio region is {region} — DPIP needs TW",
+ "meshtasticRegionMismatch": "ภูมิภาคของวิทยุคือ {region} — DPIP ต้องการ TW",
"notifySectionEarthquake": "แผ่นดินไหว",
"mapLayerDisasterMap": "แผนที่ป้องกันภัย",
"weatherModeFog": "หมอกหนา",
"typhoonPickerNamed": "{name} TY {no}",
- "mapLayerStyleGrayTooltip": "JMA grayscale — colder is whiter",
+ "mapLayerStyleGrayTooltip": "JMA grayscale — ยิ่งเย็นยิ่งขาว",
"moreAnnouncements": "ประกาศ",
"moreTagline": "แพลตฟอร์มรวมข้อมูลป้องกันภัยพิบัติ",
"moreVersionStable": "เวอร์ชันเต็ม",
- "moreVersionNotes": "เวอร์ชันปัจจุบัน",
+ "moreVersionNotes": "อัปเดตนี้",
+ "moreVersionNotesHighlightsSubtitle": "สิ่งที่เปลี่ยนไปในเวอร์ชันนี้",
"releaseHighlightsSeeNotes": "ดูบันทึกทั้งหมด",
- "releaseHighlightsTitle": "สิ่งที่เปลี่ยนแปลง",
+ "releaseHighlightsTitle": "{train} สรุปสำคัญ",
"releaseHighlightsTabNormal": "สำหรับผู้ใช้",
"releaseHighlightsTabAdvanced": "เจาะลึก",
"releaseHighlightsEmpty": "ยังไม่มีเนื้อหา",
@@ -1025,10 +1026,10 @@
"mapLayerAed": "AED",
"changelogTypePrerelease": "เบต้า",
"reportFilterIntensityInfoModernBody": "ระดับ 0–4, 5−, 5+, 6−, 6+, 7 แถบตัวกรองใช้แบบใหม่ เหตุการณ์เก่าในรายการยังแสดงป้ายแบบเก่า",
- "typhoonOverlayWeatherNone": "None",
- "mapLayerStyleGray": "Grayscale (JMA)",
+ "typhoonOverlayWeatherNone": "ไม่มี",
+ "mapLayerStyleGray": "ระดับสีเทา (JMA)",
"weatherModeAuto": "อัตโนมัติ",
- "typhoonLabelProbCircle": "70% probability circle",
+ "typhoonLabelProbCircle": "วงกลมความน่าจะเป็น 70%",
"@radarCountyOutline": {
"description": "County-border overlay toggle in the map's radar overlay menu."
},
@@ -1038,7 +1039,7 @@
"@skyTimeSunrise": {
"description": "Label for the skyTimeSunrise option in the experimental backdrop settings."
},
- "typhoonLabelDirection": "Past movement direction",
+ "typhoonLabelDirection": "ทิศทางการเคลื่อนที่",
"@meshtasticLastSent": {
"description": "Age of the last sent packet"
},
@@ -1050,15 +1051,15 @@
"typhoonLegendCone": "กรวยพยากรณ์",
"moreCwaEew": "การเตือนแผ่นดินไหวล่วงหน้าของกรมอุตุนิยมวิทยากลาง (CWA)",
"onboardingPermsTitle": "การอนุญาตสิทธิ์",
- "mapLayerStyleJma": "Cloud-top enhancement (JMA)",
+ "mapLayerStyleJma": "การเพิ่มคอนทราสต์กลุ่มเมฆ (JMA)",
"rainInterval10m": "10 นาที",
- "meshtasticConnectAnyway": "Connect anyway",
+ "meshtasticConnectAnyway": "เชื่อมต่อต่อไป",
"reportListDayCount": "{count}",
"mapLayerSatelliteB06": "Himawari Near-Infrared (B06)",
- "mapLayerSatelliteTransparentReflectance": "Low reflectance / night = transparent, the basemap shows",
+ "mapLayerSatelliteTransparentReflectance": "สะท้อนต่ำ / กลางคืน = โปร่งใส เห็นแผนที่ฐาน",
"chartHourLabel": "{hour}น.",
"mapLayerShelter": "ศูนย์อพยพ",
- "typhoonOverlayProbabilityTooltip": "Show strike probability (hides the forecast cone)",
+ "typhoonOverlayProbabilityTooltip": "แสดงความน่าจะเป็นถูกพายุโจมตี (ซ่อนกรวยคาดการณ์)",
"mapLayerSatelliteNdwi": "Himawari NDWI",
"disasterMapOverlayShelterTooltip": "แสดงศูนย์อพยพ",
"mapNavHumidity": "ความชื้น",
@@ -1068,7 +1069,7 @@
"reportDetailSortByIntensity": "เรียงตามความเข้ม",
"homeRainTrendNoData": "ไม่มีข้อมูล",
"mapLayerCategoryRadar": "เรดาร์",
- "meshtasticShortName": "Short name",
+ "meshtasticShortName": "ชื่อสั้น",
"@meshtasticStateConfiguring": {
"description": "Connection state label"
},
@@ -1088,7 +1089,7 @@
"@skyTimeMorning": {
"description": "Label for the skyTimeMorning option in the experimental backdrop settings."
},
- "meshtasticRegionConfirm": "Switch this radio to the TW region? It restarts and disconnects for a moment, and every other channel on it moves too.",
+ "meshtasticRegionConfirm": "สลับวิทยุนี้เป็นภูมิภาค TW หรือไม่ วิทยุจะรีสตาร์ทและตัดการเชื่อมต่อชั่วครู่ และทุกช่องอื่นจะย้ายไปด้วย",
"dataEarthquakeSubtitle": "รายงานแผ่นดินไหว",
"typhoonNoActive": "ไม่มีไต้ฝุ่น",
"@meshtasticExcludeMqttHidden": {
@@ -1105,10 +1106,55 @@
"@meshtasticChannels": {
"description": "Section: the radio's channel table"
},
+ "mapOsmOverlay": "แผนที่แบบละเอียด",
+ "mapOsmOverlayHint": "แสดงถนน อาคาร และชื่อสถานที่อย่างละเอียด",
+ "mapOsmDetails": "รายละเอียดเลเยอร์",
+ "moreDataSources": "แหล่งข้อมูล",
+ "dataSourceTremNet": "探索智慧科技有限公司 — TREM-Net",
+ "dataSourceCwa": "交通部中央氣象署 (CWA)",
+ "dataSourceJma": "気象庁 (JMA)",
+ "dataSourceNcdr": "國家災害防救科技中心 (NCDR)",
+ "dataSourceEcmwf": "European Centre for Medium-Range Weather Forecasts (ECMWF)",
+ "dataSourceNoaaGfs": "National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)",
+ "dataSourceGovernmentOpenData": "政府資料開放平臺",
+ "dataSourceOpenStreetMap": "© OpenStreetMap contributors",
+ "dataSourceNasaMoon": "National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)",
+ "mapOsmDetailsHint": "เปิดใช้งาน {enabled} จากทั้งหมด {total} เลเยอร์",
+ "@mapOsmDetailsHint": {
+ "description": "How many of the OSM layers are enabled",
+ "placeholders": {
+ "enabled": {
+ "type": "int"
+ },
+ "total": {
+ "type": "int"
+ }
+ }
+ },
+ "mapOsmSurface": "พื้นผิว",
+ "mapOsmParks": "สวนสาธารณะ",
+ "mapOsmLandUse": "การใช้ที่ดิน",
+ "mapOsmAirportAreas": "พื้นที่สนามบิน",
+ "mapOsmWater": "พื้นที่น้ำ",
+ "mapOsmRivers": "แม่น้ำ",
+ "mapOsmBoundaries": "ขอบเขต",
+ "mapOsmBuildings": "อาคาร",
+ "mapOsmRoads": "ถนน",
+ "mapOsmRoadNames": "ชื่อถนน",
+ "mapOsmWaterNames": "ชื่อพื้นที่น้ำ",
+ "mapOsmPeaks": "ยอดเขา",
+ "mapOsmAirportNames": "ชื่อสนามบิน",
+ "mapOsmPlaceNames": "ชื่อสถานที่",
+ "mapOsmPoi": "จุดน่าสนใจ",
+ "mapOsmHouseNumbers": "เลขที่บ้าน",
+ "mapOsmRestoreAll": "คืนค่าทั้งหมด",
+ "mapOsmSectionNatural": "ลักษณะธรรมชาติ",
+ "mapOsmSectionRoadsAndBuildings": "ถนนและอาคาร",
+ "mapOsmSectionLabelsAndPlaces": "ป้ายชื่อและสถานที่",
"mapTownLabels": "ชื่อตำบล",
"notifySetFailed": "ไม่สามารถบันทึกการตั้งค่าได้ โปรดลองอีกครั้ง",
- "meshtasticDisconnect": "Disconnect",
- "meshtasticUndecoded": "Not decrypted",
+ "meshtasticDisconnect": "ตัดการเชื่อมต่อ",
+ "meshtasticUndecoded": "ไม่ได้ถอดรหัส",
"notifyAnnouncement": "ประกาศ",
"onboardingIntroTitle": "ยินดีต้อนรับสู่ DPIP",
"regionCurrentUnavailable": "ไม่สามารถระบุตำแหน่งปัจจุบันได้",
@@ -1799,6 +1845,30 @@
"description": "Button that opens the system settings page"
},
"permissionSettingsMessage": "“{what}” ถูกปฏิเสธไว้ และระบบจะไม่ถามอีก โปรดเปิดในการตั้งค่า",
+ "permissionGuideNotification": "เปิดการตั้งค่าระบบเพื่ออนุญาตการแจ้งเตือน",
+ "permissionGuideForegroundLocation": "เปิดการตั้งค่าระบบเพื่ออนุญาตตำแหน่งที่แม่นยำ",
+ "permissionGuideBackgroundLocation": "ใน “{option}” ให้เลือก “อนุญาตตลอดเวลา”",
+ "@permissionGuideBackgroundLocation": {
+ "description": "Instruction for background location",
+ "placeholders": {
+ "option": {}
+ }
+ },
+ "permissionGuideBackgroundExecution": "อนุญาตการทำงานเบื้องหลังในการตั้งค่าระบบเพื่อไม่ให้หยุดการแจ้งเตือน",
+ "permissionGuideUnusedPause": "หากแอปถูกทำเครื่องหมายเป็น “ไม่ได้ใช้” ให้เลือก “อนุญาต” ในการตั้งค่าระบบ",
+ "permissionGuideUnusedFreeSpace": "หากแอปถูกหยุดชั่วคราวเพราะพื้นที่จัดเก็บ ให้ล้างแคชแล้วเปิดใหม่",
+ "permissionGuideUnusedRevoke": "หากสิทธิ์ของแอปถูกเพิกถอน ให้อนุญาตอีกครั้งในการตั้งค่าระบบ",
+ "permissionGuideUnusedPlayProtect": "หาก Play Protect หยุดแอปชั่วคราว ให้ตรวจสอบสถานะใน Google Play",
+ "permissionGuideVendorPower": "ในการตั้งค่าประหยัดพลังงานของ “{vendor}” ให้ตั้งค่าแอปนี้เป็น “ไม่จำกัด”",
+ "@permissionGuideVendorPower": {
+ "description": "Instruction for vendor power saving",
+ "placeholders": {
+ "vendor": {}
+ }
+ },
+ "permissionStillRequired": "ยังจำเป็น — เปิดการตั้งค่าเพื่อเปิดใช้งาน",
+ "permissionVerifyManually": "โปรดตรวจสอบด้วยตนเองว่าสิทธิ์นี้เปิดใช้งานในการตั้งค่าระบบ",
+ "permissionBackgroundLocationOption": "“อนุญาตตลอดเวลา”",
"@permissionSettingsMessage": {
"description": "Explains that the system will not ask again for this permission",
"placeholders": {
@@ -1872,6 +1942,9 @@
},
"moreDumpDiagnostics": "อัปโหลดข้อมูลดีบักและบันทึก",
"moreDumpDiagnosticsHint": "อัปโหลดแล้วคัดลอกลิงก์เพื่อแนบในรายงาน",
+ "dumpIncludeSensitive": "รวมตำแหน่งที่แม่นยำ",
+ "dumpIncludeSensitiveHint": "รวมพิกัดจากบันทึกและตำแหน่งเบื้องหลัง หากไม่เลือกจะแทนค่าด้วย null",
+ "dumpUpload": "อัปโหลด",
"dumpUploaded": "อัปโหลดแล้ว",
"dumpLinkCopied": "คัดลอกลิงก์ไปยังคลิปบอร์ดแล้ว",
"dumpCopyAgain": "คัดลอกอีกครั้ง",
diff --git a/lib/l10n/app_vi.arb b/lib/l10n/app_vi.arb
index 17b3f7539..fdf68f43d 100644
--- a/lib/l10n/app_vi.arb
+++ b/lib/l10n/app_vi.arb
@@ -19,29 +19,29 @@
"reportFilterIntensity": "Cường độ",
"mapLayerLightning": "Sét",
"restroomTypeMale": "Nhà vệ sinh nam",
- "meshtasticLastReceived": "Last received",
+ "meshtasticLastReceived": "Nhận lần cuối",
"reportDetailSortByCounty": "Sắp xếp theo khu vực",
"@moonDays": {
"description": "Day unit for the moon age"
},
"homeRainTrendScattered": "Có thể có mưa rào nhẹ",
- "meshtasticUptime": "Uptime",
+ "meshtasticUptime": "Thời gian hoạt động",
"weatherRankingTempExtremes": "Cực trị nhiệt độ",
"themeLight": "Sáng",
"mapTerrainReliefHint": "Hiển thị địa hình nổi trên bản đồ nền",
- "meshtasticEmptyMessage": "(empty message)",
+ "meshtasticEmptyMessage": "(tin nhắn trống)",
"moreSectionRegion": "Khu vực",
"mapLayerSatellite": "Himawari Infrared (B13)",
"@meshtasticTapNode": {
"description": "Resting state of the map node sheet"
},
"aedHoursSaturday": "Giờ thứ Bảy",
- "moonPhaseNew": "New moon",
+ "moonPhaseNew": "Trăng mới",
"notifySectionEew": "Cảnh báo sớm động đất",
"mapResetNorth": "Về hướng bắc",
"rainInterval2d": "2 ngày",
"mapTownLabelsHint": "Hiển thị tên hương trấn khi phóng to",
- "commonCancel": "Cancel",
+ "commonCancel": "Hủy",
"notifyOptTsunamiWarning": "Chỉ cảnh báo sóng thần",
"mapLayerSatelliteBtdFog": "Himawari Night Fog",
"@meshtasticSelectDevice": {
@@ -59,7 +59,7 @@
"notifySettingsMenu": "Cài đặt thông báo",
"mapAppDefault": "{app} (mặc định)",
"trendRange24h": "24 giờ",
- "mapLayerStyleJmaTooltip": "Grayscale base, tinted below −40 °C to highlight cloud-top height",
+ "mapLayerStyleJmaTooltip": "Nền grayscale, tô màu dưới −40 °C để làm nổi bật độ cao đỉnh mây",
"mapLayerRain": "Lượng mưa",
"mapLayerQpesums": "Dự báo mưa 1 giờ tới",
"@weatherModeSnow": {
@@ -82,16 +82,16 @@
"changelogShowSnapshots": "Hiện bản thử nghiệm",
"changelogTitle": "Nhật ký cập nhật",
"reportFilterOrderDesc": "Giảm dần",
- "meshtasticExcludeMqttSubtitle": "Nodes bridged over the internet, not heard by radio",
+ "meshtasticExcludeMqttSubtitle": "Các nút kết nối qua Internet, không nghe qua sóng radio",
"reportFilterIntensityInfoTitle": "Thang cường độ mới và cũ",
"mapLayerTyphoon": "Bão",
"radarOverlayMenuTooltip": "Tùy chọn lớp radar",
"@meshtasticChannelUse": {
"description": "Share of airtime seen busy"
},
- "meshtasticNodes": "Nodes",
- "meshtasticSend": "Send",
- "typhoonOverlayStormL7Tooltip": "Level-7 wind field + average circle (purple)",
+ "meshtasticNodes": "Nút",
+ "meshtasticSend": "Gửi",
+ "typhoonOverlayStormL7Tooltip": "Trường gió cấp 7 + bán kính trung bình (tím)",
"aedType": "Loại",
"termsOfService": "Điều khoản dịch vụ",
"typhoonLegendCircle25": "Vòng bão",
@@ -110,12 +110,12 @@
"@meshtasticExcludeMqttSubtitle": {
"description": "What an MQTT node is"
},
- "meshtasticFirmware": "Firmware",
+ "meshtasticFirmware": "Phần mềm cơ sở",
"@mapLayerMeshtastic": {
"description": "Map layer name: mesh nodes"
},
"reportFilterDateEndNote": "Ngày kết thúc: đến 24:00(Đài Bắc)",
- "meshtasticSilent": "Silent",
+ "meshtasticSilent": "Im lặng",
"reportFilterSortMagnitude": "Độ lớn",
"mapLayerCategoryEarthquake": "Động đất",
"mapLayerSatelliteB12": "Himawari Ozone (B12)",
@@ -144,12 +144,12 @@
"@radarCountyOutlineHint": {
"description": "Hint under the county-border toggle in the radar overlay menu."
},
- "meshtasticLayerOptions": "Node options",
+ "meshtasticLayerOptions": "Tùy chọn nút",
"onboardingAgreeContinue": "Đồng ý và tiếp tục",
- "meshtasticNodeId": "Node ID",
+ "meshtasticNodeId": "ID nút",
"commonRetry": "Thử lại",
"reportDetailNumbered": "Động đất có cảm nhận đáng kể số {number}",
- "typhoonOverlayStormBandSubtitle": "With average circle",
+ "typhoonOverlayStormBandSubtitle": "Kèm bán kính trung bình",
"disasterMapOverlayRestroomTooltip": "Hiển thị nhà vệ sinh công cộng",
"weatherRankingTitle": "Xếp hạng quan trắc",
"homeRainTrendHeavySustained": "Mưa lớn tiếp diễn trong 1 giờ tới",
@@ -161,12 +161,12 @@
"@meshtasticSilent": {
"description": "Legend: node known but not heard recently"
},
- "meshtasticChannelWorking": "Setting up the DPIP channel…",
- "meshtasticRegionSwitch": "Switch to TW",
+ "meshtasticChannelWorking": "Đang thiết lập kênh DPIP…",
+ "meshtasticRegionSwitch": "Chuyển sang vùng TW",
"@meshtasticLastReceived": {
"description": "Age of the last received packet"
},
- "meshtasticTraffic": "Traffic",
+ "meshtasticTraffic": "Lưu lượng",
"@meshtasticDpipChannel": {
"description": "Which channel DPIP payloads use"
},
@@ -176,8 +176,8 @@
"description": "Moon page title"
},
"mapLayerHumidity": "Độ ẩm",
- "mapLayerSatelliteTransparentNight": "Night = transparent, the basemap shows",
- "meshtasticScanning": "Scanning…",
+ "mapLayerSatelliteTransparentNight": "Ban đêm = trong suốt, thấy bản đồ nền",
+ "meshtasticScanning": "Đang quét…",
"@meshtasticDevice": {
"description": "Section: device identity"
},
@@ -202,7 +202,7 @@
"meshtasticEtaDays": "~{n} ngày",
"meshtasticTitle": "Meshtastic",
"navMore": "Thêm",
- "meshtasticDpipChannel": "DPIP channel",
+ "meshtasticDpipChannel": "Kênh DPIP",
"disasterMapOverlaySectionLayers": "Lớp",
"@moonPhaseWaningCrescent": {
"description": "Phase: waning crescent"
@@ -215,15 +215,15 @@
"description": "Label for the weatherModeCloudy option in the experimental backdrop settings."
},
"typhoonLabelNe": "NE",
- "meshtasticCopied": "Message copied",
+ "meshtasticCopied": "Đã sao chép tin nhắn",
"reportListEmpty": "Không có báo cáo động đất",
"reportListEnd": "Hết danh sách",
"mapLayerSatelliteTruecolor": "Himawari True Color",
- "typhoonOverlaySectionExtra": "Overlays",
+ "typhoonOverlaySectionExtra": "Lớp phủ",
"eewSWave": "Sóng S",
- "meshtasticBusyTitle": "Another app is using this radio",
+ "meshtasticBusyTitle": "Ứng dụng khác đang dùng radio này",
"restroomCategoryCultural": "Địa điểm văn hóa giải trí",
- "typhoonLabelWind": "Max. sustained wind near centre",
+ "typhoonLabelWind": "Gió duy trì tối đa gần tâm",
"radarGlobalOutlineHint": "Khung ngoài của mỗi quốc gia",
"notifyEvacuation": "Thông tin thảm họa",
"typhoonLegendCircle15": "Vòng gió mạnh",
@@ -233,11 +233,11 @@
"@meshtasticRadioSettings": {
"description": "Section: LoRa settings"
},
- "dataSectionAstronomy": "Astronomy",
+ "dataSectionAstronomy": "Thiên văn",
"homeRainTrendLightSustained": "Mưa nhỏ tiếp diễn trong 1 giờ tới",
"commonError": "Đã xảy ra lỗi",
- "moonPhaseWaningCrescent": "Waning crescent",
- "meshtasticPower": "Power",
+ "moonPhaseWaningCrescent": "Trăng lưỡi liềm khuyết",
+ "meshtasticPower": "Nguồn",
"@meshtasticChannelWorking": {
"description": "Creating/verifying the DPIP channel"
},
@@ -248,14 +248,14 @@
"typhoonWarningAreas": "Khu vực: {areas}",
"rainIntervalSection": "Khoảng thời gian",
"notifyTitle": "Thông báo",
- "meshtasticTxPower": "TX power",
+ "meshtasticTxPower": "Công suất TX",
"@radarTownOutlineHint": {
"description": "Hint under the township-border toggle in the radar overlay menu."
},
"restroomCategoryLabel": "Hạng mục",
"sponsorRestoring": "Đang khôi phục giao dịch…",
"sponsorIntro": "DPIP cam kết cung cấp thông tin phòng chống thiên tai theo thời gian thực, không có quảng cáo hay mô hình lợi nhuận nào khác. Sự ủng hộ của bạn giúp chúng tôi duy trì máy chủ và tiếp tục phát triển.",
- "typhoonLabelStormAvg": "Avg. radius of Beaufort 10 winds",
+ "typhoonLabelStormAvg": "Bán kính trung bình gió Beaufort 10",
"@meshtasticHardware": {
"description": "Board model"
},
@@ -274,8 +274,8 @@
"rainInterval6h": "6 giờ",
"homeRainTrendMinute": "{minute} phút",
"restroomTypeUnspecified": "Không xác định",
- "typhoonOverlayProbabilityHint": "Hides the forecast cone",
- "mapLayerSatelliteGlobalOutline": "Country border",
+ "typhoonOverlayProbabilityHint": "Ẩn vùng dự kiến",
+ "mapLayerSatelliteGlobalOutline": "Đường biên giới",
"mapNavTemperature": "Nhiệt độ",
"typhoonLegendForecastPoint": "Điểm dự báo",
"@meshtasticBattery": {
@@ -289,16 +289,16 @@
"rainInterval3d": "3 ngày",
"defaultMapLayerSubtitle": "Tab Bản đồ mở lớp này. Biểu tượng và nhãn thanh điều hướng dưới cũng theo lựa chọn.",
"aedDescription": "Ghi chú",
- "typhoonOverlayWeatherRadarTooltip": "Radar echo closest to the typhoon bulletin time",
+ "typhoonOverlayWeatherRadarTooltip": "Ảnh radar gần thời điểm bản tin bão nhất",
"onboardingPermLocationDesc": "Gửi cảnh báo phù hợp với nơi bạn đang ở.",
"mapLayerSatelliteB16": "Himawari CO₂ (B16)",
"@meshtasticClearMessages": {
"description": "Menu action clearing the message log"
},
"homeActiveEventsEmpty": "Không có sự kiện đang hiệu lực",
- "typhoonLabelPosition": "Centre location",
+ "typhoonLabelPosition": "Vị trí tâm",
"weatherRankingBy": "Theo",
- "typhoonIntensityMild": "Mild typhoon",
+ "typhoonIntensityMild": "Bão yếu",
"windForecastGlobalOutlineHint": "Khung ngoài của mỗi quốc gia",
"rainInterval1h": "1 giờ",
"eewLocalIntensity": "Ước tính tại vị trí",
@@ -307,23 +307,23 @@
"description": "Radar scan-range overlay toggle in the map's radar overlay menu."
},
"restroomCategoryReligious": "Nơi tôn giáo",
- "meshtasticRole": "Role",
- "mapLayerSatelliteCloudCloudy": "Cloudy",
+ "meshtasticRole": "Vai trò",
+ "mapLayerSatelliteCloudCloudy": "Nhiều mây",
"skyTimeSunrise": "Bình minh",
"@mapLayerMeshtasticSubtitle": {
"description": "Map layer switcher subtitle"
},
"meshtasticJumpToLatest": "Tới mới nhất",
- "meshtasticNoMessages": "No messages yet",
+ "meshtasticNoMessages": "Chưa có tin nhắn",
"onboardingPermNotifyDesc": "Gửi cảnh báo động đất, thời tiết và thảm họa ngay khi chúng xảy ra.",
"radarTownOutline": "Ranh giới xã phường",
- "mapLayerStyleSection": "Colour style",
+ "mapLayerStyleSection": "Kiểu màu",
"@moonPhaseNew": {
"description": "Phase: new moon"
},
"disasterMapOverlayMenuTooltip": "Lớp bản đồ phòng chống",
"moreGooglePlay": "Google Play",
- "meshtasticOnline": "Heard recently",
+ "meshtasticOnline": "Nghe thấy gần đây",
"@meshtasticSendHint": {
"description": "Message input hint"
},
@@ -331,7 +331,7 @@
"typhoonForecastLead": "Forecast +{hours} h",
"@mapAppOpenFailed": {},
"changelogTypeStable": "Chính thức",
- "mapLayerSatelliteTransparentClear": "Clear sky = transparent, the basemap shows",
+ "mapLayerSatelliteTransparentClear": "Trời quang = trong suốt, thấy bản đồ nền",
"@skyTimeAuto": {
"description": "Label for the skyTimeAuto option in the experimental backdrop settings."
},
@@ -350,11 +350,11 @@
"mapLayerSatelliteTransparentNoVegetation": "Below 0.1 = transparent (no vegetation)",
"notifyOptLocalIntensity4": "Cường độ tại chỗ từ 4 trở lên",
"eewArrived": "Đã đến",
- "meshtasticNoDevices": "No Meshtastic devices found",
+ "meshtasticNoDevices": "Không tìm thấy thiết bị Meshtastic",
"mapLayerCategoryLife": "Đời sống",
"reportFilterSortIntensity": "Cường độ",
- "meshtasticStateDisconnected": "Disconnected",
- "typhoonIntensityIntense": "Intense typhoon",
+ "meshtasticStateDisconnected": "Đã ngắt kết nối",
+ "typhoonIntensityIntense": "Bão mạnh",
"@meshtasticSend": {
"description": "Send message button"
},
@@ -366,7 +366,7 @@
"description": "The radio's short name"
},
"dpmYes": "Có",
- "meshtasticNoHistory": "Not enough history yet",
+ "meshtasticNoHistory": "Lịch sử chưa đủ",
"reportDetailLocalIntensityUnavailable": "Không có dữ liệu cường độ",
"mapLayerWindForecastGfs": "GFS",
"reportFilterDepth": "Độ sâu",
@@ -390,8 +390,8 @@
},
"reportFilterReset": "Đặt lại",
"mapLayerSatelliteMndwi": "Himawari MNDWI",
- "typhoonOverlaySectionStorm": "Storm wind",
- "moonPhaseFull": "Full moon",
+ "typhoonOverlaySectionStorm": "Gió bão",
+ "moonPhaseFull": "Trăng tròn",
"@meshtasticEmptyMessage": {
"description": "Placeholder for a text packet with no body"
},
@@ -399,24 +399,24 @@
"@radarGlobalOutlineHint": {
"description": "Hint under the national-border toggle in the radar overlay menu."
},
- "moonPhaseWaningGibbous": "Waning gibbous",
+ "moonPhaseWaningGibbous": "Trăng khuyết lồi",
"reportFilterIntensityInfoModernTitle": "Mới (từ 2020)",
"@mapAppGoogleMaps": {},
- "typhoonDataTime": "Data time\n{time}",
+ "typhoonDataTime": "Giờ dữ liệu\n{time}",
"restroomTypeAccessible": "Nhà vệ sinh tiếp cận được",
"moreSectionAbout": "Giới thiệu",
- "meshtasticSelectDevice": "Select a radio",
+ "meshtasticSelectDevice": "Chọn radio",
"onboardingIntroBody": "DPIP là người bạn đồng hành phòng chống thiên tai của bạn. Ứng dụng tích hợp cảnh báo sớm động đất, báo cáo động đất, thời tiết và thông tin về hiểm họa, đồng thời cảnh báo bạn ngay tại thời điểm quan trọng.\n\n• Động đất: cảnh báo sớm, báo cáo cường độ và báo cáo chi tiết\n• Thời tiết: tin nhắn mưa dông theo thời gian thực và cảnh báo thời tiết\n• Thông tin sóng thần và thảm họa\n\nTiếp theo, chúng tôi sẽ mời bạn xem lại Điều khoản Dịch vụ và cấp một vài quyền để DPIP có thể bảo vệ bạn theo thời gian thực.",
"shelterCapacityLabel": "Sức chứa",
"reportDetailImage": "Hình ảnh báo cáo",
- "meshtasticStateConfiguring": "Configuring…",
+ "meshtasticStateConfiguring": "Đang cấu hình…",
"@moonPhaseLastQuarter": {
"description": "Phase: last quarter"
},
- "typhoonLabelGaleAvg": "Avg. radius of Beaufort 7 winds",
+ "typhoonLabelGaleAvg": "Bán kính trung bình gió Beaufort 7",
"onboardingPermNotify": "Thông báo",
- "meshtasticClearMessages": "Clear messages",
- "meshtasticNotifyMessages": "Notify on new messages",
+ "meshtasticClearMessages": "Xóa tin nhắn",
+ "meshtasticNotifyMessages": "Thông báo tin nhắn mới",
"defaultMapLayerSettings": "Lớp bản đồ mặc định",
"eewSourceSettings": "Nguồn cảnh báo sớm động đất",
"eewSourceSubtitle": "Chọn cơ quan phát hành cảnh báo sớm động đất muốn hiển thị.",
@@ -446,7 +446,7 @@
"description": "Label for the skyTimeAfternoon option in the experimental backdrop settings."
},
"mapTimelineFuture": "Tương lai",
- "typhoonLegendCircleAvg": "Average circle",
+ "typhoonLegendCircleAvg": "Bán kính trung bình",
"reportFilterDepthKm": "{depth} km",
"typhoonLabelSe": "SE",
"radarTownOutlineHint": "Lưới chi tiết hơn",
@@ -454,7 +454,7 @@
"@meshtasticDisconnect": {
"description": "Disconnect from the radio"
},
- "typhoonLabelGust": "Peak gust",
+ "typhoonLabelGust": "Gió giật đỉnh",
"mapAppGoogleMaps": "Google Maps",
"sponsorTerms": "Điều khoản sử dụng",
"restroomTypeGenderNeutral": "Nhà vệ sinh trung tính giới",
@@ -463,7 +463,7 @@
},
"notifyThunderstorm": "Cảnh báo mưa dông",
"skyTimeGolden": "Giờ vàng",
- "moonAge": "Age",
+ "moonAge": "Tuổi trăng",
"@windForecastTownOutlineHint": {
"description": "Hint under the township-border toggle in the wind-forecast overlay menu."
},
@@ -474,20 +474,20 @@
"moreGithub": "ExpTech GitHub",
"homeForecastUnavailable": "Chọn khu vực để xem dự báo",
"mapLayers": "Lớp bản đồ",
- "meshtasticHardware": "Hardware",
+ "meshtasticHardware": "Phần cứng",
"languageSettings": "Ngôn ngữ",
"@moonNextFullMoon": {
"description": "Next full moon date label"
},
"language": "Ngôn ngữ",
"homeForecastFeelsLike": "Cảm giác {temp}°",
- "typhoonOverlayWeatherHint": "Aligned to bulletin time",
+ "typhoonOverlayWeatherHint": "Khớp với thời điểm bản tin",
"@meshtasticHopLimit": {
"description": "How many hops a packet may take"
},
"skyTimeDawn": "Rạng đông",
"skyTimeAfternoon": "Buổi chiều",
- "meshtasticLastHeard": "Last heard",
+ "meshtasticLastHeard": "Nghe thấy lần cuối",
"typhoonWarningTitle": "Cảnh báo bão",
"moreSourceCode": "Mã nguồn",
"mapLayerCategoryWeather": "Quan sát thời tiết",
@@ -506,37 +506,37 @@
"mapTimelineForecast": "Dự báo",
"restroomTypeLabel": "Loại",
"navEarthquake": "Động đất",
- "typhoonOverlayStormL10Tooltip": "Level-10 wind field + average circle (yellow)",
- "moonPhaseWaxingGibbous": "Waxing gibbous",
+ "typhoonOverlayStormL10Tooltip": "Trường gió cấp 10 + bán kính trung bình (vàng)",
+ "moonPhaseWaxingGibbous": "Trăng khuyết lồi đầu tháng",
"reportDetailTitle": "Báo cáo động đất",
"moreTremReport": "Báo cáo phát hiện TREM",
"weatherDataTime": "{station} · Thời gian dữ liệu {time}",
- "meshtasticNoNodes": "No nodes heard yet",
- "meshtasticViaMqtt": "Via MQTT (internet)",
+ "meshtasticNoNodes": "Chưa phát hiện nút nào",
+ "meshtasticViaMqtt": "Qua MQTT (Internet)",
"radarCountyOutline": "Ranh giới huyện thị",
"@mapAppCopyCoordinates": {},
"commonClose": "Đóng",
"restroomGradeLabel": "Hạng",
"rainIntervalNow": "Hôm nay",
"changelogCurrentVersion": "Hiện tại",
- "typhoonOverlayForecastCalloutsTooltip": "Show forecast-point detail cards when zoomed in",
- "typhoonLabelPressure": "Central pressure",
+ "typhoonOverlayForecastCalloutsTooltip": "Hiển thị thẻ chi tiết điểm dự báo khi phóng to",
+ "typhoonLabelPressure": "Áp suất trung tâm",
"aedOpenRemark": "Ghi chú giờ mở",
"onboardingPermsBody": "Để DPIP có thể cảnh báo bạn ngay khi thảm họa xảy ra, vui lòng cấp các quyền sau. Bạn có thể thay đổi chúng bất cứ lúc nào trong cài đặt hệ thống.",
- "typhoonOverlaySectionWeather": "Weather underlay",
+ "typhoonOverlaySectionWeather": "Lớp nền thời tiết",
"@meshtasticStateConnected": {
"description": "Connection state label"
},
"notifyOptWeatherLocal": "Chỉ vị trí hiện tại",
"mapNavRain": "Mưa",
- "moonDays": "days",
+ "moonDays": "ngày",
"mapLegendUnit": "Đơn vị: {unit}",
"weatherModeClear": "Trời quang",
- "meshtasticRadio": "Radio",
+ "meshtasticRadio": "Bộ đàm",
"commonEmpty": "Không có dữ liệu",
"mapLayerSatelliteB01": "Himawari Blue (B01)",
- "meshtasticExternalPower": "External power",
- "moonPhaseLastQuarter": "Last quarter",
+ "meshtasticExternalPower": "Nguồn ngoài",
+ "moonPhaseLastQuarter": "Trăng bán nguyệt cuối tháng",
"@meshtasticName": {
"description": "The radio's long name"
},
@@ -551,20 +551,20 @@
"mapLayerRestroom": "Nhà vệ sinh công cộng",
"restroomCategoryWelfare": "Cơ sở phúc lợi",
"restroomGradeExcellent": "Xuất sắc",
- "meshtasticLastSent": "Last sent",
- "meshtasticName": "Name",
- "meshtasticScan": "Scan",
+ "meshtasticLastSent": "Gửi lần cuối",
+ "meshtasticName": "Tên",
+ "meshtasticScan": "Quét",
"@radarOverlayMenuTooltip": {
"description": "Tooltip for the radar overlay-options chip beside the layer switcher"
},
"mapLayerCategoryForecast": "Dự báo số",
- "meshtasticChannelFailed": "Couldn't set up the DPIP channel",
+ "meshtasticChannelFailed": "Không thiết lập được kênh DPIP",
"themeSystem": "Hệ thống",
"mapLayerSatelliteNdvi": "Himawari NDVI",
"typhoonLegendForecast": "Quỹ đạo dự báo",
"typhoonValueHpa": "{n} hPa",
"weatherPrecipitation": "Lượng mưa",
- "moonNextFullMoon": "Next full moon",
+ "moonNextFullMoon": "Trăng tròn kế tiếp",
"dpmSheetEmpty": "Chạm vào điểm đánh dấu trên bản đồ để xem chi tiết",
"onboardingSkipLeave": "Vẫn bỏ qua",
"aedPlaceDesc": "Vị trí đặt",
@@ -582,22 +582,22 @@
},
"onboardingPermBattery": "Miễn trừ tối ưu hóa pin",
"typhoonLabelNw": "NW",
- "moonPhaseWaxingCrescent": "Waxing crescent",
+ "moonPhaseWaxingCrescent": "Trăng lưỡi liềm đầu tháng",
"restroomCategoryLeisure": "Địa điểm vui chơi giải trí",
"mapLayerTemperature": "Nhiệt độ",
"aedCategory": "Phân loại",
"@moonTimelineCaption": {
"description": "Moon phase timeline caption"
},
- "meshtasticChannels": "Channels",
+ "meshtasticChannels": "Kênh",
"monitorWaiting": "Đang chờ dữ liệu…",
- "typhoonOverlayForecastCallouts": "Forecast tooltips",
+ "typhoonOverlayForecastCallouts": "Chú thích điểm dự báo",
"@meshtasticTitle": {
"description": "Meshtastic test page title"
},
"reportDetailEpicenter": "Tọa độ tâm chấn",
- "meshtasticVoltage": "Voltage",
- "mapLayerMeshtasticSubtitle": "LoRa mesh nodes heard by your radio",
+ "meshtasticVoltage": "Điện áp",
+ "mapLayerMeshtasticSubtitle": "Nút lưới LoRa radio của bạn nghe thấy",
"@meshtasticSent": {
"description": "Packets sent this session"
},
@@ -623,34 +623,34 @@
"description": "Township-border overlay toggle in the map's radar overlay menu."
},
"mapLayerSatelliteB04": "Himawari Near-Infrared (B04)",
- "mapLayerSatelliteTransparentZero": "Zero difference = transparent (no signal)",
+ "mapLayerSatelliteTransparentZero": "Chênh lệch bằng 0 = trong suốt (không có tín hiệu)",
"shelterIndoorLabel": "Trú ẩn trong nhà",
"notifyOptOff": "Tắt",
"reportFilterSortTime": "Thời gian",
- "mapLayerSatelliteCloudProbablyClear": "Probably clear",
+ "mapLayerSatelliteCloudProbablyClear": "Có thể quang mây",
"weatherModeThunderstorm": "Mưa dông",
"homeViewOnMap": "Xem trên bản đồ",
"reportFilterIntensityInfoLegacyTitle": "Cũ (trước 2020)",
- "typhoonLabelSpeed": "Past movement speed",
+ "typhoonLabelSpeed": "Tốc độ di chuyển",
"@meshtasticReconnecting": {
"description": "The link dropped and is being re-established"
},
"mapAppOpenFailed": "Không thể mở {app}",
- "mapLayerSatelliteRgbComposite": "RGB composite (JMA recipe)",
+ "mapLayerSatelliteRgbComposite": "RGB tổng hợp (công thức JMA)",
"@meshtasticStateDisconnected": {
"description": "Connection state label"
},
- "meshtasticReceived": "Received",
+ "meshtasticReceived": "Đã nhận",
"weatherRankingExtremeLow": "Thấp nhất ngày",
"@meshtasticRegionSwitch": {
"description": "Button applying the DPIP LoRa region"
},
"mapLayerSatelliteB10": "Himawari Lower Water Vapour (B10)",
- "mapLayerSatelliteCloudProbablyCloudy": "Probably cloudy",
+ "mapLayerSatelliteCloudProbablyCloudy": "Có thể nhiều mây",
"shelterCategoryLabel": "Loại thảm họa",
"mapLayerSatelliteTransparentNoWater": "≤ 0 = transparent (no water)",
- "meshtasticStateConnecting": "Connecting…",
- "moonTitle": "Moon",
+ "meshtasticStateConnecting": "Đang kết nối…",
+ "moonTitle": "Mặt Trăng",
"weatherRankingGust": "Gió giật",
"moreAppStore": "App Store",
"@meshtasticUndecoded": {
@@ -661,7 +661,7 @@
},
"moreServerStatus": "Trạng thái máy chủ",
"notifySectionWeather": "Thời tiết",
- "meshtasticPreset": "Modem preset",
+ "meshtasticPreset": "Cấu hình modem",
"dataSectionSeismic": "Địa chấn",
"changelogBodyEmpty": "Không có ghi chú cho bản phát hành này.",
"changelogOpenOnGitHub": "Xem trên GitHub",
@@ -670,15 +670,15 @@
"regionNationwide": "Toàn quốc",
"moreNotifyLog": "Nhật ký thông báo DPIP",
"regionCurrent": "Vị trí hiện tại",
- "meshtasticNotConnected": "Not connected to a radio",
+ "meshtasticNotConnected": "Chưa kết nối radio",
"weatherModeSnow": "Tuyết rơi",
- "mapLayerMeshtastic": "Meshtastic nodes",
+ "mapLayerMeshtastic": "Nút Meshtastic",
"moreDeveloper": "Thông tin gỡ lỗi",
"@qpesumsOverlayMenuTooltip": {
"description": "Tooltip for the QPESUMS forecast overlay-options chip beside the layer switcher."
},
"mapLayerSatelliteB14": "Himawari Longwave Infrared (B14)",
- "meshtasticChannelUse": "Channel use",
+ "meshtasticChannelUse": "Mức dùng kênh",
"mapNavLightning": "Sét",
"homeForecastEmpty": "Không có dữ liệu dự báo",
"sponsorOneTime": "Ủng hộ một lần",
@@ -686,7 +686,7 @@
"onboardingPermBackground": "Vị trí chạy nền",
"aedEmergencyPhone": "Điện thoại khẩn cấp",
"dpmOpenInMaps": "Mở trong bản đồ",
- "meshtasticNotifyNodes": "Notify on new nodes",
+ "meshtasticNotifyNodes": "Thông báo nút mới",
"onboardingPermCriticalDesc": "Cho phép các cảnh báo động đất nguy hiểm đến tính mạng phát âm thanh ngay cả khi ở chế độ im lặng hoặc Không làm phiền.",
"@mapAppDefault": {
"placeholders": {
@@ -695,11 +695,11 @@
}
}
},
- "mapLayerSatelliteTransparentWarm": "Clear sky (warm end) = transparent, the basemap shows",
- "meshtasticSent": "Sent",
+ "mapLayerSatelliteTransparentWarm": "Trời quang (đầu ấm) = trong suốt, thấy bản đồ nền",
+ "meshtasticSent": "Đã gửi",
"homeForecastTitle": "Dự báo 24 giờ",
"typhoonLegendWarningAreas": "Vùng cảnh báo",
- "meshtasticExcludeMqttHidden": "{count} hidden",
+ "meshtasticExcludeMqttHidden": "Ẩn {count} mục",
"notifyOptLocalIntensity1": "Cường độ tại chỗ từ 1 trở lên",
"@skyTimeGolden": {
"description": "Label for the skyTimeGolden option in the experimental backdrop settings."
@@ -710,21 +710,21 @@
"mapTimelinePast": "Quá khứ",
"restroomTypeFemale": "Nhà vệ sinh nữ",
"reportListToday": "Hôm nay",
- "meshtasticTapNode": "Tap a node for details",
+ "meshtasticTapNode": "Chạm vào nút để xem chi tiết",
"commonLoading": "Đang tải…",
"@meshtasticStateConnecting": {
"description": "Connection state label"
},
- "typhoonIntensityModerate": "Moderate typhoon",
+ "typhoonIntensityModerate": "Bão trung bình",
"mapLayerSatelliteAsh": "Himawari Ash",
"rainInterval3h": "3 giờ",
- "meshtasticChannelReady": "DPIP channel ready",
+ "meshtasticChannelReady": "Kênh DPIP đã sẵn sàng",
"@meshtasticNotifyNodes": {
"description": "Toggle: local notification when a new node is heard"
},
"mapLayerCategorySatellite": "Vệ tinh",
"mapLayerSatelliteNightmicrophysics": "Himawari Night Microphysics",
- "typhoonIntensityTd": "Tropical depression",
+ "typhoonIntensityTd": "Áp thấp nhiệt đới",
"reportFilterDate": "Ngày",
"sponsorRestoreUnavailable": "Không thể kết nối tới cửa hàng. Vui lòng thử lại sau.",
"homeForecastPop": "{pop}%",
@@ -773,13 +773,13 @@
}
},
"mapLayerSatelliteBtdSo2": "Himawari SO₂ / Cloud Phase",
- "meshtasticStateError": "Error",
+ "meshtasticStateError": "Lỗi",
"weatherModeOvercast": "Trời âm u",
"@meshtasticScan": {
"description": "Start scanning for Meshtastic radios"
},
"reportDetailDepth": "Độ sâu chấn tiêu",
- "typhoonOverlayWarningTooltip": "Highlight counties under a typhoon warning",
+ "typhoonOverlayWarningTooltip": "Làm nổi bật các huyện đang có cảnh báo bão",
"reportFilterDatePick": "Chọn ngày",
"onboardingSkipStay": "Quay lại",
"@moonPhaseWaxingCrescent": {
@@ -793,16 +793,16 @@
"description": "Transmit power"
},
"shelterOutdoorLabel": "Trú ẩn ngoài trời",
- "meshtasticStateConnected": "Connected",
- "mapNavRadar": "Radar",
- "mapLayerSatelliteCloudClear": "Clear",
+ "meshtasticStateConnected": "Đã kết nối",
+ "mapNavRadar": "Ra đa",
+ "mapLayerSatelliteCloudClear": "Quang mây",
"eewSummary": "M{magnitude} · độ sâu {depth} km",
"locationBannerPermission": "Chưa cấp quyền vị trí — cảnh báo khu vực không thể nhắm đúng vùng của bạn.",
- "typhoonOverlayWeatherNoneTooltip": "No radar or infrared underlay",
+ "typhoonOverlayWeatherNoneTooltip": "Không có lớp nền radar hoặc hồng ngoại",
"radarCountyOutlineHint": "Vẽ đè lên tiếng vọng",
"windForecastCountyOutlineHint": "Vẽ trên trường gió",
"homeRainTrendTitle": "Mưa 1 giờ tới",
- "moonPhaseFirstQuarter": "First quarter",
+ "moonPhaseFirstQuarter": "Trăng bán nguyệt đầu tháng",
"mapLayerCategoryTyphoon": "Bão",
"@windForecastOverlayMenuTooltip": {
"description": "Tooltip for the wind-forecast overlay-options chip beside the layer switcher."
@@ -810,13 +810,13 @@
"@meshtasticNodeId": {
"description": "The radio's node number"
},
- "meshtasticUtilization": "Airtime (24h)",
+ "meshtasticUtilization": "Thời gian phát sóng (24 giờ)",
"restroomTypeMixed": "Nhà vệ sinh chung",
"restroomGradeGood": "Tốt",
"notifyTsunami": "Thông tin sóng thần",
"navData": "Dữ liệu",
"mapLayerSatelliteBtdWvirw": "Himawari Overshooting Top",
- "meshtasticReadingAge": "Reading taken",
+ "meshtasticReadingAge": "Thời điểm đo",
"@moonPhaseWaningGibbous": {
"description": "Phase: waning gibbous"
},
@@ -829,7 +829,7 @@
"notifyIntensity": "Báo cáo cường độ chấn động",
"rainIntervalMenu": "Khung tích lũy",
"reportDetailLocalFelt": "Động đất cảm nhận cục bộ",
- "meshtasticDevice": "Device",
+ "meshtasticDevice": "Thiết bị",
"onboardingGrant": "Cấp quyền",
"weatherModeRain": "Mưa",
"shelterVulnerableOkLabel": "Phù hợp người yếu thế",
@@ -853,7 +853,7 @@
"trendCumulativeTotal": "Tổng cộng {total} mm",
"languageName": "Tiếng Việt",
"reportListEmptyFiltered": "Không có báo cáo khớp bộ lọc",
- "meshtasticExcludeMqtt": "Hide MQTT nodes",
+ "meshtasticExcludeMqtt": "Ẩn nút MQTT",
"mapNavTyphoon": "Bão",
"weatherModeSand": "Bụi cát",
"@moonPhaseFirstQuarter": {
@@ -869,9 +869,9 @@
"feedStale": "Dữ liệu có thể đã lỗi thời",
"homeForecastWind": "{direction} · Cấp {level}",
"navHome": "Trang chủ",
- "meshtasticRegionLabel": "Region",
+ "meshtasticRegionLabel": "Vùng",
"mapLayerSatelliteCloudtop": "Himawari Cloud Top Temperature",
- "moonTimelineCaption": "Phase",
+ "moonTimelineCaption": "Pha",
"@meshtasticChannelNoSlot": {
"description": "Every secondary channel slot is taken"
},
@@ -886,7 +886,7 @@
"reportFilterSortDepth": "Độ sâu",
"mapTimelineDataTime": "Thời gian dữ liệu {time}",
"radarScanRange": "Hiện phạm vi quét",
- "meshtasticHopLimit": "Hop limit",
+ "meshtasticHopLimit": "Giới hạn hop",
"@meshtasticUptime": {
"description": "Time since the radio booted"
},
@@ -897,17 +897,17 @@
"sponsorPrivacy": "Chính sách quyền riêng tư",
"reportDetailLocalIntensity": "Cường độ tại vị trí của bạn",
"mapLayerSatelliteNaturalcolor": "Himawari Natural Color",
- "meshtasticAirtime": "Air time (TX)",
+ "meshtasticAirtime": "Thời gian phát sóng (TX)",
"shelterCapacityValue": "{n} người",
"lightningLegendCc": "Mây–mây · {minutes} phút",
- "meshtasticSendHint": "Message to broadcast",
+ "meshtasticSendHint": "Tin nhắn để phát",
"monitorDelay": "Độ trễ {value} s",
"@meshtasticFirmware": {
"description": "Firmware version"
},
"dpmNo": "Không",
"mapLayerSatelliteB08": "Himawari Upper Water Vapour (B08)",
- "meshtasticReconnecting": "Reconnecting…",
+ "meshtasticReconnecting": "Đang kết nối lại…",
"@mapAppAppleMaps": {},
"@meshtasticReadingAge": {
"description": "How old the battery/airtime numbers are"
@@ -916,16 +916,16 @@
"@moonPhaseWaxingGibbous": {
"description": "Phase: waxing gibbous"
},
- "typhoonOverlayWeatherSatelliteTooltip": "Infrared closest to the typhoon bulletin time",
+ "typhoonOverlayWeatherSatelliteTooltip": "Ảnh hồng ngoại gần thời điểm bản tin bão nhất",
"radarScanRangeHint": "Ngoài khung là chưa quan trắc",
- "typhoonPickerTd": "Tropical depression TD {no}",
+ "typhoonPickerTd": "Áp thấp nhiệt đới TD {no}",
"mapLayerSatelliteWatervapor": "Himawari Water Vapour",
"regionAddButton": "Thêm khu vực",
"displaySettings": "Hiển thị",
"restroomGradePoor": "Dưới chuẩn",
"restroomCategoryTourist": "Khu du lịch thắng cảnh",
"locationBannerServiceOff": "Dịch vụ vị trí đang tắt — cảnh báo khu vực không thể nhắm đúng vùng của bạn.",
- "mapLayerStyleTooltip": "Colour style",
+ "mapLayerStyleTooltip": "Kiểu màu",
"lightningLegendCg": "Mây–đất · {minutes} phút",
"skyTimeAuto": "Tự động",
"appLogs": "Nhật ký ứng dụng",
@@ -966,21 +966,21 @@
"endpointStateUnknown": "Không rõ",
"endpointServiceEew": "EEW",
"endpointServiceRts": "RTS",
- "endpointServiceRadar": "Radar",
- "endpointServiceSatellite": "Satellite",
+ "endpointServiceRadar": "Ra đa",
+ "endpointServiceSatellite": "Vệ tinh",
"endpointServiceQpesums": "QPE",
- "endpointServiceWind": "Wind",
- "endpointServiceDpm": "Disaster points",
- "endpointServiceWeather": "Weather",
- "endpointServiceRain": "Rain",
- "endpointServiceLightning": "Lightning",
- "endpointServiceTyphoon": "Typhoon",
- "endpointServiceReport": "EQ reports",
- "endpointServiceTremStation": "Tremor station",
- "endpointServiceEvent": "Events",
- "endpointServiceLocation": "Location",
- "endpointServiceNotify": "Notifications",
- "endpointServiceOther": "Other",
+ "endpointServiceWind": "Gió",
+ "endpointServiceDpm": "Điểm thiên tai",
+ "endpointServiceWeather": "Thời tiết",
+ "endpointServiceRain": "Mưa",
+ "endpointServiceLightning": "Sét",
+ "endpointServiceTyphoon": "Bão",
+ "endpointServiceReport": "Báo cáo động đất",
+ "endpointServiceTremStation": "Trạm đo chấn động",
+ "endpointServiceEvent": "Sự kiện",
+ "endpointServiceLocation": "Vị trí",
+ "endpointServiceNotify": "Thông báo",
+ "endpointServiceOther": "Khác",
"feedConnecting": "Đang kết nối…",
"notifyBannerDisabled": "Thông báo đã tắt — bạn sẽ không nhận được cảnh báo thiên tai.",
"@meshtasticNoNodes": {
@@ -989,27 +989,28 @@
"weatherHumidity": "Độ ẩm",
"typhoonValueMs": "{n} m/s",
"homeForecastHumidity": "Độ ẩm {value}%",
- "meshtasticBusyBody": "Disconnect it in the other Meshtastic app first. Two apps on one radio take each other's messages, so some will go missing.",
- "meshtasticChannelNoSlot": "No free channel slot — free one on the radio",
+ "meshtasticBusyBody": "Hãy ngắt kết nối radio trong ứng dụng Meshtastic khác trước. Hai ứng dụng dùng chung một radio sẽ giành tin nhắn của nhau, một số tin sẽ bị mất.",
+ "meshtasticChannelNoSlot": "Không có kênh trống — hãy giải phóng một kênh trên radio",
"restroomCategoryTransport": "Giao thông",
- "meshtasticBattery": "Battery",
+ "meshtasticBattery": "Pin",
"meshtasticDistance": "Khoảng cách",
"meshtasticSnrTrend": "Xu hướng tín hiệu (SNR)",
"meshtasticBatteryTrend": "Xu hướng pin",
- "typhoonOverlayMenuTooltip": "Typhoon overlay options",
+ "typhoonOverlayMenuTooltip": "Tùy chọn lớp phủ bão",
"mapLayerSatelliteBtdOzone": "Himawari Tropopause",
- "meshtasticRegionMismatch": "Radio region is {region} — DPIP needs TW",
+ "meshtasticRegionMismatch": "Vùng radio là {region} — DPIP cần TW",
"notifySectionEarthquake": "Động đất",
"mapLayerDisasterMap": "Bản đồ phòng chống",
"weatherModeFog": "Sương mù",
"typhoonPickerNamed": "{name} TY {no}",
- "mapLayerStyleGrayTooltip": "JMA grayscale — colder is whiter",
+ "mapLayerStyleGrayTooltip": "JMA grayscale — càng lạnh càng trắng",
"moreAnnouncements": "Thông báo",
"moreTagline": "Nền tảng tích hợp thông tin phòng chống thiên tai",
"moreVersionStable": "Bản chính thức",
- "moreVersionNotes": "Phiên bản hiện tại",
+ "moreVersionNotes": "Bản cập nhật này",
+ "moreVersionNotesHighlightsSubtitle": "Những thay đổi trong phiên bản này",
"releaseHighlightsSeeNotes": "Xem ghi chú đầy đủ",
- "releaseHighlightsTitle": "Thay đổi trong bản này",
+ "releaseHighlightsTitle": "{train} tóm tắt chính",
"releaseHighlightsTabNormal": "Cho người dùng",
"releaseHighlightsTabAdvanced": "Đi sâu",
"releaseHighlightsEmpty": "Chưa có nội dung.",
@@ -1025,10 +1026,10 @@
"mapLayerAed": "AED",
"changelogTypePrerelease": "Thử nghiệm",
"reportFilterIntensityInfoModernBody": "Các mức 0–4, 5−, 5+, 6−, 6+, 7. Thanh lọc dùng thang mới; sự kiện cũ vẫn hiện nhãn cũ trong danh sách.",
- "typhoonOverlayWeatherNone": "None",
- "mapLayerStyleGray": "Grayscale (JMA)",
+ "typhoonOverlayWeatherNone": "Không có",
+ "mapLayerStyleGray": "Thang xám (JMA)",
"weatherModeAuto": "Tự động",
- "typhoonLabelProbCircle": "70% probability circle",
+ "typhoonLabelProbCircle": "Vòng tròn xác suất 70%",
"@radarCountyOutline": {
"description": "County-border overlay toggle in the map's radar overlay menu."
},
@@ -1038,7 +1039,7 @@
"@skyTimeSunrise": {
"description": "Label for the skyTimeSunrise option in the experimental backdrop settings."
},
- "typhoonLabelDirection": "Past movement direction",
+ "typhoonLabelDirection": "Hướng di chuyển",
"@meshtasticLastSent": {
"description": "Age of the last sent packet"
},
@@ -1050,15 +1051,15 @@
"typhoonLegendCone": "Nón dự báo",
"moreCwaEew": "Cảnh báo sớm động đất của CWA",
"onboardingPermsTitle": "Quyền truy cập",
- "mapLayerStyleJma": "Cloud-top enhancement (JMA)",
+ "mapLayerStyleJma": "Tăng tương phản mây (JMA)",
"rainInterval10m": "10 phút",
- "meshtasticConnectAnyway": "Connect anyway",
+ "meshtasticConnectAnyway": "Vẫn kết nối",
"reportListDayCount": "{count}",
"mapLayerSatelliteB06": "Himawari Near-Infrared (B06)",
- "mapLayerSatelliteTransparentReflectance": "Low reflectance / night = transparent, the basemap shows",
+ "mapLayerSatelliteTransparentReflectance": "Phản xạ thấp / ban đêm = trong suốt, thấy bản đồ nền",
"chartHourLabel": "{hour}h",
"mapLayerShelter": "Nơi trú ẩn",
- "typhoonOverlayProbabilityTooltip": "Show strike probability (hides the forecast cone)",
+ "typhoonOverlayProbabilityTooltip": "Hiển thị xác suất trúng bão (ẩn vùng dự kiến)",
"mapLayerSatelliteNdwi": "Himawari NDWI",
"disasterMapOverlayShelterTooltip": "Hiển thị nơi trú ẩn",
"mapNavHumidity": "Độ ẩm",
@@ -1068,7 +1069,7 @@
"reportDetailSortByIntensity": "Sắp xếp theo cường độ",
"homeRainTrendNoData": "Không có dữ liệu",
"mapLayerCategoryRadar": "Ra đa",
- "meshtasticShortName": "Short name",
+ "meshtasticShortName": "Tên ngắn",
"@meshtasticStateConfiguring": {
"description": "Connection state label"
},
@@ -1088,7 +1089,7 @@
"@skyTimeMorning": {
"description": "Label for the skyTimeMorning option in the experimental backdrop settings."
},
- "meshtasticRegionConfirm": "Switch this radio to the TW region? It restarts and disconnects for a moment, and every other channel on it moves too.",
+ "meshtasticRegionConfirm": "Chuyển radio này sang vùng TW? Nó sẽ khởi động lại và ngắt kết nối một lúc, mọi kênh khác cũng được chuyển theo.",
"dataEarthquakeSubtitle": "Báo cáo động đất",
"typhoonNoActive": "Không có bão",
"@meshtasticExcludeMqttHidden": {
@@ -1105,10 +1106,55 @@
"@meshtasticChannels": {
"description": "Section: the radio's channel table"
},
+ "mapOsmOverlay": "Bản đồ chi tiết",
+ "mapOsmOverlayHint": "Hiện đường, tòa nhà và địa danh chi tiết hơn",
+ "mapOsmDetails": "Chi tiết lớp",
+ "moreDataSources": "Nguồn dữ liệu",
+ "dataSourceTremNet": "探索智慧科技有限公司 — TREM-Net",
+ "dataSourceCwa": "交通部中央氣象署 (CWA)",
+ "dataSourceJma": "気象庁 (JMA)",
+ "dataSourceNcdr": "國家災害防救科技中心 (NCDR)",
+ "dataSourceEcmwf": "European Centre for Medium-Range Weather Forecasts (ECMWF)",
+ "dataSourceNoaaGfs": "National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)",
+ "dataSourceGovernmentOpenData": "政府資料開放平臺",
+ "dataSourceOpenStreetMap": "© OpenStreetMap contributors",
+ "dataSourceNasaMoon": "National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)",
+ "mapOsmDetailsHint": "Đã bật {enabled} / {total} lớp",
+ "@mapOsmDetailsHint": {
+ "description": "How many of the OSM layers are enabled",
+ "placeholders": {
+ "enabled": {
+ "type": "int"
+ },
+ "total": {
+ "type": "int"
+ }
+ }
+ },
+ "mapOsmSurface": "Bề mặt",
+ "mapOsmParks": "Công viên",
+ "mapOsmLandUse": "Sử dụng đất",
+ "mapOsmAirportAreas": "Khu vực sân bay",
+ "mapOsmWater": "Vùng nước",
+ "mapOsmRivers": "Sông ngòi",
+ "mapOsmBoundaries": "Ranh giới",
+ "mapOsmBuildings": "Tòa nhà",
+ "mapOsmRoads": "Đường bộ",
+ "mapOsmRoadNames": "Tên đường",
+ "mapOsmWaterNames": "Tên vùng nước",
+ "mapOsmPeaks": "Đỉnh núi",
+ "mapOsmAirportNames": "Tên sân bay",
+ "mapOsmPlaceNames": "Tên địa danh",
+ "mapOsmPoi": "Địa điểm quan tâm",
+ "mapOsmHouseNumbers": "Số nhà",
+ "mapOsmRestoreAll": "Khôi phục tất cả",
+ "mapOsmSectionNatural": "Đặc điểm tự nhiên",
+ "mapOsmSectionRoadsAndBuildings": "Đường & tòa nhà",
+ "mapOsmSectionLabelsAndPlaces": "Nhãn & địa điểm",
"mapTownLabels": "Tên hương trấn",
"notifySetFailed": "Không thể lưu cài đặt. Vui lòng thử lại.",
- "meshtasticDisconnect": "Disconnect",
- "meshtasticUndecoded": "Not decrypted",
+ "meshtasticDisconnect": "Ngắt kết nối",
+ "meshtasticUndecoded": "Chưa giải mã",
"notifyAnnouncement": "Thông báo",
"onboardingIntroTitle": "Chào mừng đến với DPIP",
"regionCurrentUnavailable": "Không thể lấy vị trí hiện tại",
@@ -1799,6 +1845,30 @@
"description": "Button that opens the system settings page"
},
"permissionSettingsMessage": "“{what}” đã bị từ chối và hệ thống sẽ không hỏi lại. Hãy bật trong Cài đặt.",
+ "permissionGuideNotification": "Mở Cài đặt Hệ thống để cho phép thông báo.",
+ "permissionGuideForegroundLocation": "Mở Cài đặt Hệ thống để cho phép vị trí chính xác.",
+ "permissionGuideBackgroundLocation": "Trong “{option}”, chọn “Cho phép mọi lúc”.",
+ "@permissionGuideBackgroundLocation": {
+ "description": "Instruction for background location",
+ "placeholders": {
+ "option": {}
+ }
+ },
+ "permissionGuideBackgroundExecution": "Cho phép chạy nền trong Cài đặt Hệ thống để thông báo không bị tạm dừng.",
+ "permissionGuideUnusedPause": "Nếu ứng dụng bị đánh dấu “không sử dụng”, hãy chọn “Cho phép” trong Cài đặt Hệ thống.",
+ "permissionGuideUnusedFreeSpace": "Nếu ứng dụng bị tạm dừng vì bộ nhớ, hãy xóa bộ nhớ đệm và mở lại.",
+ "permissionGuideUnusedRevoke": "Nếu quyền của ứng dụng bị thu hồi, hãy cấp lại trong Cài đặt Hệ thống.",
+ "permissionGuideUnusedPlayProtect": "Nếu Play Protect tạm dừng ứng dụng, hãy kiểm tra trạng thái trong Google Play.",
+ "permissionGuideVendorPower": "Trong cài đặt tiết kiệm pin của “{vendor}”, đặt ứng dụng này thành “Không giới hạn”.",
+ "@permissionGuideVendorPower": {
+ "description": "Instruction for vendor power saving",
+ "placeholders": {
+ "vendor": {}
+ }
+ },
+ "permissionStillRequired": "Vẫn cần thiết — mở Cài đặt để bật.",
+ "permissionVerifyManually": "Vui lòng xác minh thủ công rằng quyền này đã được bật trong Cài đặt Hệ thống.",
+ "permissionBackgroundLocationOption": "“Cho phép mọi lúc”",
"@permissionSettingsMessage": {
"description": "Explains that the system will not ask again for this permission",
"placeholders": {
@@ -1872,6 +1942,9 @@
},
"moreDumpDiagnostics": "Tải lên thông tin gỡ lỗi và nhật ký",
"moreDumpDiagnosticsHint": "Tải lên rồi sao chép liên kết để đính kèm vào báo cáo",
+ "dumpIncludeSensitive": "Bao gồm vị trí chính xác",
+ "dumpIncludeSensitiveHint": "Bao gồm tọa độ trong nhật ký và vị trí nền; nếu không chọn, chúng được thay bằng null",
+ "dumpUpload": "Tải lên",
"dumpUploaded": "Đã tải lên",
"dumpLinkCopied": "Đã sao chép liên kết vào bảng nhớ tạm",
"dumpCopyAgain": "Sao chép lại",
diff --git a/lib/l10n/app_yue.arb b/lib/l10n/app_yue.arb
new file mode 100644
index 000000000..8dcf071fc
--- /dev/null
+++ b/lib/l10n/app_yue.arb
@@ -0,0 +1,1954 @@
+{
+ "@@locale": "yue",
+ "languageName": "粵語",
+ "typhoonValueLat": "北緯 {lat} 度",
+ "onboardingSkipBody": "未授權定位同通知,DPIP 將冇辦法即時通知你所在地嘅地震同災害。你仍可稍後喺設定中開啟。",
+ "@mapAppCoordinatesCopied": {},
+ "@meshtasticLayerOptions": {
+ "description": "Tooltip for the mesh layer's options chip"
+ },
+ "rainInterval24h": "24 時",
+ "homeRainTrendHeavyStopping": "預計 {minutes} 分鐘後停止下大雨",
+ "mapTimelineObserved": "觀測",
+ "mapTimelineScrubPaused": "拖動過快,影格更新已暫停;放慢速度即可恢復。",
+ "regionSelectTitle": "選擇地區",
+ "skyTimeNoon": "正午",
+ "radarCountyOutlineSubtitle": "讓縣市界線在雷達回波下仍然清楚。",
+ "@meshtasticRegionLabel": {
+ "description": "LoRa region"
+ },
+ "mapLayerSatelliteB03": "ひまわり 可見光-紅(B03)",
+ "reportFilterIntensity": "震度",
+ "mapLayerLightning": "閃電",
+ "restroomTypeMale": "男廁所",
+ "meshtasticLastReceived": "最近接收",
+ "reportDetailSortByCounty": "依縣市排序",
+ "@moonDays": {
+ "description": "Day unit for the moon age"
+ },
+ "homeRainTrendScattered": "可能會有零星降雨",
+ "meshtasticUptime": "運行時間",
+ "weatherRankingTempExtremes": "溫度極值",
+ "themeLight": "淺色",
+ "mapTerrainReliefHint": "喺底圖上顯示立體地形陰影",
+ "meshtasticEmptyMessage": "(空白訊息)",
+ "moreSectionRegion": "地區",
+ "mapLayerSatellite": "ひまわり 紅外線(B13)",
+ "@meshtasticTapNode": {
+ "description": "Resting state of the map node sheet"
+ },
+ "aedHoursSaturday": "週六開放時間",
+ "moonPhaseNew": "新月",
+ "notifySectionEew": "地震速報",
+ "mapResetNorth": "回到北方",
+ "rainInterval2d": "2 日",
+ "mapTownLabelsHint": "放大時顯示鄉鎮名稱",
+ "commonCancel": "取消",
+ "notifyOptTsunamiWarning": "只接收海嘯警報",
+ "mapLayerSatelliteBtdFog": "ひまわり 夜間霧",
+ "@meshtasticSelectDevice": {
+ "description": "Device picker sheet title"
+ },
+ "moreSectionAdvanced": "進階",
+ "moreSectionMesh": "Mesh 網絡",
+ "@meshtasticLastHeard": {
+ "description": "When a node last transmitted"
+ },
+ "weatherRankingExtremeRange": "日溫差",
+ "permissionsTitle": "權限檢查",
+ "permissionsAttention": "權限需要處理",
+ "permissionsBody": "DPIP 需要呢些權限才能即時通知你。收唔到警報時,通常就係其中一項尚未開啟。",
+ "notifySettingsMenu": "通知設定",
+ "mapAppDefault": "{app}(預設)",
+ "trendRange24h": "24 小時",
+ "mapLayerStyleJmaTooltip": "灰階為底,−40 °C 以下上色,凸顯雲頂高度",
+ "mapLayerRain": "雨量",
+ "mapLayerQpesums": "未來 1 小時降水預報",
+ "@weatherModeSnow": {
+ "description": "Label for the weatherModeSnow option in the experimental backdrop settings."
+ },
+ "@dataSectionAstronomy": {
+ "description": "Astronomy section header in the data catalogue"
+ },
+ "mapOverlaySectionMap": "地圖",
+ "mapTerrainRelief": "地形立體感",
+ "mapLegendCollapse": "收合圖例",
+ "updateAvailableTitle": "有新版本",
+ "updateAvailableBody": "新版本 {version} 已發佈。",
+ "updateSkip": "略過此次",
+ "updateViewChangelog": "前往查看",
+ "updateOpenAppStore": "App Store",
+ "updateOpenTestFlight": "TestFlight",
+ "updateOpenPlayStore": "Play 商店",
+ "updateDownload": "下載更新",
+ "changelogShowSnapshots": "顯示測試版",
+ "changelogTitle": "更新日誌",
+ "reportFilterOrderDesc": "降序",
+ "meshtasticExcludeMqttSubtitle": "經網際網路橋接、並非無線電聽到嘅節點",
+ "reportFilterIntensityInfoTitle": "震度新制同舊制",
+ "mapLayerTyphoon": "颱風",
+ "radarOverlayMenuTooltip": "雷達圖層選項",
+ "@meshtasticChannelUse": {
+ "description": "Share of airtime seen busy"
+ },
+ "meshtasticNodes": "節點",
+ "meshtasticSend": "傳送",
+ "typhoonOverlayStormL7Tooltip": "七級暴風圈+平均圓(紫色)",
+ "aedType": "場所類型",
+ "termsOfService": "服務條款",
+ "typhoonLegendCircle25": "十級風暴風圈",
+ "sponsorTitle": "支援 DPIP",
+ "mapNavSatellite": "衛星",
+ "homeRainTrendUpdated": "更新 {time}",
+ "onboardingNext": "下一步",
+ "weatherRankingMergeTown": "鄉鎮",
+ "mapLayerMonitor": "強震監視器",
+ "moreYoutube": "YouTube",
+ "sponsorSubscriptions": "訂閱制",
+ "typhoonValueLon": "東經 {lon} 度",
+ "skyTime": "天空時間",
+ "weatherModeCloudy": "多雲",
+ "skyTimeDusk": "暮色",
+ "@meshtasticExcludeMqttSubtitle": {
+ "description": "What an MQTT node is"
+ },
+ "meshtasticFirmware": "韌體",
+ "@mapLayerMeshtastic": {
+ "description": "Map layer name: mesh nodes"
+ },
+ "reportFilterDateEndNote": "結束日:當日 24:00(台北時間)",
+ "meshtasticSilent": "已靜默",
+ "reportFilterSortMagnitude": "規模",
+ "mapLayerCategoryEarthquake": "地震",
+ "mapLayerSatelliteB12": "ひまわり 臭氧(B12)",
+ "restroomCategoryOther": "其他",
+ "@meshtasticRegionConfirm": {
+ "description": "Confirmation before rebooting the radio"
+ },
+ "@skyTimeSunset": {
+ "description": "Label for the skyTimeSunset option in the experimental backdrop settings."
+ },
+ "homeForecastHighLow": "高 {high}° · 低 {low}°",
+ "@meshtasticChannelFailed": {
+ "description": "The radio rejected the channel write"
+ },
+ "locationBannerFix": "開啟設定",
+ "mapLegendExpand": "圖例",
+ "eewNone": "而家冇地震速報",
+ "typhoonTyNo": "TY {no}",
+ "notifyOptTsunamiAll": "海嘯消息、海嘯警報",
+ "@windForecastGlobalOutlineHint": {
+ "description": "Hint under the national-border toggle in the wind-forecast overlay menu."
+ },
+ "@skyTimeNight": {
+ "description": "Label for the skyTimeNight option in the experimental backdrop settings."
+ },
+ "@radarCountyOutlineHint": {
+ "description": "Hint under the county-border toggle in the radar overlay menu."
+ },
+ "meshtasticLayerOptions": "節點選項",
+ "onboardingAgreeContinue": "同意並繼續",
+ "meshtasticNodeId": "節點 ID",
+ "commonRetry": "重試",
+ "reportDetailNumbered": "編號 {number} 顯著有感地震",
+ "typhoonOverlayStormBandSubtitle": "含平均圓",
+ "disasterMapOverlayRestroomTooltip": "顯示公廁",
+ "weatherRankingTitle": "觀測排行",
+ "homeRainTrendHeavySustained": "未來 1 小時會有持續大雨",
+ "notifySectionTsunami": "海嘯",
+ "restroomCategoryPark": "公園",
+ "moreLinkOpenFailed": "冇辦法開啟連結",
+ "themeDark": "深色",
+ "sponsorRestore": "恢復購買",
+ "@meshtasticSilent": {
+ "description": "Legend: node known but not heard recently"
+ },
+ "meshtasticChannelWorking": "正在設定 DPIP 頻道…",
+ "meshtasticRegionSwitch": "切換為 TW",
+ "@meshtasticLastReceived": {
+ "description": "Age of the last received packet"
+ },
+ "meshtasticTraffic": "流量",
+ "@meshtasticDpipChannel": {
+ "description": "Which channel DPIP payloads use"
+ },
+ "mapLayerStyleBdTooltip": "Dvorak BD 曲線——熱帶氣旋強度分析嘅階梯灰階",
+ "disasterMapOverlayAedTooltip": "顯示 AED 位置",
+ "@moonTitle": {
+ "description": "Moon page title"
+ },
+ "mapLayerHumidity": "濕度",
+ "mapLayerSatelliteTransparentNight": "夜間 = 透明,顯示底圖",
+ "meshtasticScanning": "掃描中…",
+ "@meshtasticDevice": {
+ "description": "Section: device identity"
+ },
+ "regionSelectFull": "最多只能選擇 {max} 個地區",
+ "meshtasticNewMessages": "新訊息",
+ "meshtasticBatteryHistory": "電量歷史",
+ "meshtasticStatAvg": "平均",
+ "meshtasticStatPeak": "峰值",
+ "meshtasticStatDrain": "掉電",
+ "meshtasticStatEta": "預估可用",
+ "meshtasticStatFull": "充滿",
+ "meshtasticStatTrend": "趨勢",
+ "meshtasticStatCharging": "充電中",
+ "meshtasticStatStable": "穩定",
+ "meshtasticNodesTotal": "已知",
+ "meshtasticNodesOnline": "在線",
+ "meshtasticRx": "接收",
+ "meshtasticTx": "發送",
+ "meshtasticNodesHistory": "節點數歷史",
+ "meshtasticTrafficHistory": "流量歷史",
+ "meshtasticEtaHours": "約 {n} 小時",
+ "meshtasticEtaDays": "約 {n} 天",
+ "meshtasticTitle": "Meshtastic",
+ "navMore": "更多",
+ "meshtasticDpipChannel": "DPIP 頻道",
+ "disasterMapOverlaySectionLayers": "圖層",
+ "@moonPhaseWaningCrescent": {
+ "description": "Phase: waning crescent"
+ },
+ "mapLayerSatelliteB05": "ひまわり 近紅外(B05)",
+ "@meshtasticNotConnected": {
+ "description": "Empty message log while not connected"
+ },
+ "@weatherModeCloudy": {
+ "description": "Label for the weatherModeCloudy option in the experimental backdrop settings."
+ },
+ "typhoonLabelNe": "東北側",
+ "meshtasticCopied": "已複製訊息",
+ "reportListEmpty": "而家冇地震報告",
+ "reportListEnd": "已到最後一頁",
+ "mapLayerSatelliteTruecolor": "ひまわり 真彩色",
+ "typhoonOverlaySectionExtra": "覆蓋層",
+ "eewSWave": "震波",
+ "meshtasticBusyTitle": "另一個 App 正在使用呢台裝置",
+ "restroomCategoryCultural": "文化育樂活動場所",
+ "typhoonLabelWind": "近中心最大風速",
+ "radarGlobalOutlineHint": "各國國界外框",
+ "notifyEvacuation": "防災資訊",
+ "typhoonLegendCircle15": "七級風暴風圈",
+ "@radarGlobalOutline": {
+ "description": "World-country-border overlay toggle in the map's reference-layer overlay menus."
+ },
+ "@meshtasticRadioSettings": {
+ "description": "Section: LoRa settings"
+ },
+ "dataSectionAstronomy": "天文",
+ "homeRainTrendLightSustained": "未來 1 小時會有持續小雨",
+ "commonError": "發生錯誤",
+ "moonPhaseWaningCrescent": "殘月",
+ "meshtasticPower": "電力",
+ "@meshtasticChannelWorking": {
+ "description": "Creating/verifying the DPIP channel"
+ },
+ "mapTimelineNow": "而家",
+ "reportFilterRange": "{start} – {end}",
+ "reportDetailOpenReport": "報告頁面",
+ "trendRange7d": "7 天",
+ "typhoonWarningAreas": "警戒區域:{areas}",
+ "rainIntervalSection": "統計時間",
+ "notifyTitle": "通知",
+ "meshtasticTxPower": "發射功率",
+ "@radarTownOutlineHint": {
+ "description": "Hint under the township-border toggle in the radar overlay menu."
+ },
+ "restroomCategoryLabel": "類別",
+ "sponsorRestoring": "正在恢復購買…",
+ "sponsorIntro": "DPIP 致力於提供即時防災資訊,冇廣告或其他營利模式。你嘅支援能幫助我哋維持伺服器運作並持續開發。",
+ "typhoonLabelStormAvg": "十級風平均暴風半徑",
+ "@meshtasticHardware": {
+ "description": "Board model"
+ },
+ "restroomCategoryCommercial": "商業營業場所",
+ "@meshtasticAirtime": {
+ "description": "Share of airtime this radio transmitted"
+ },
+ "aedRegion": "縣市區域",
+ "homeRainTrendLightStopping": "預計 {minutes} 分鐘後停止下小雨",
+ "reportDetailInfo": "詳細資訊",
+ "mapNavWind": "風向",
+ "@meshtasticReceived": {
+ "description": "Packets received this session"
+ },
+ "windForecastOverlayMenuTooltip": "風場預報圖層選項",
+ "rainInterval6h": "6 時",
+ "homeRainTrendMinute": "{minute}分",
+ "restroomTypeUnspecified": "未設定",
+ "typhoonOverlayProbabilityHint": "會隱藏預測圓錐",
+ "mapLayerSatelliteGlobalOutline": "國界",
+ "mapNavTemperature": "溫度",
+ "typhoonLegendForecastPoint": "預測點",
+ "@meshtasticBattery": {
+ "description": "Battery charge"
+ },
+ "reportListYesterday": "昨天",
+ "moreSectionLinks": "相關連結",
+ "feedOffline": "連接中斷",
+ "mapLayerStyleBd": "Dvorak BD",
+ "moreSectionDisplay": "顯示",
+ "rainInterval3d": "3 日",
+ "defaultMapLayerSubtitle": "開啟地圖分頁時顯示此圖層,底部導覽列圖示同文字會一併更新。",
+ "aedDescription": "備註",
+ "typhoonOverlayWeatherRadarTooltip": "雷達回波(對齊颱風報文時間)",
+ "onboardingPermLocationDesc": "依你所在位置推送本地警報。",
+ "mapLayerSatelliteB16": "ひまわり 二氧化碳(B16)",
+ "@meshtasticClearMessages": {
+ "description": "Menu action clearing the message log"
+ },
+ "homeActiveEventsEmpty": "而家冇生效中嘅事件",
+ "typhoonLabelPosition": "中心位置",
+ "weatherRankingBy": "依",
+ "typhoonIntensityMild": "輕度颱風",
+ "windForecastGlobalOutlineHint": "各國國界外框",
+ "rainInterval1h": "1 時",
+ "eewLocalIntensity": "所在地預估",
+ "mapLayerRadar": "雷達合成回波圖",
+ "@radarScanRange": {
+ "description": "Radar scan-range overlay toggle in the map's radar overlay menu."
+ },
+ "restroomCategoryReligious": "宗教禮儀場所",
+ "meshtasticRole": "角色",
+ "mapLayerSatelliteCloudCloudy": "有雲",
+ "skyTimeSunrise": "日出",
+ "@mapLayerMeshtasticSubtitle": {
+ "description": "Map layer switcher subtitle"
+ },
+ "meshtasticJumpToLatest": "跳到最新",
+ "meshtasticNoMessages": "尚無訊息",
+ "onboardingPermNotifyDesc": "在地震、天氣同災害發生時,即時傳遞警報通知。",
+ "radarTownOutline": "鄉鎮界線",
+ "mapLayerStyleSection": "顯示樣式",
+ "@moonPhaseNew": {
+ "description": "Phase: new moon"
+ },
+ "disasterMapOverlayMenuTooltip": "防災地圖圖層",
+ "moreGooglePlay": "Google Play",
+ "meshtasticOnline": "近期聽到",
+ "@meshtasticSendHint": {
+ "description": "Message input hint"
+ },
+ "typhoonLabelSw": "西南側",
+ "typhoonForecastLead": "預測 +{hours} 小時",
+ "@mapAppOpenFailed": {},
+ "changelogTypeStable": "正式版",
+ "mapLayerSatelliteTransparentClear": "晴空 = 透明,顯示底圖",
+ "@skyTimeAuto": {
+ "description": "Label for the skyTimeAuto option in the experimental backdrop settings."
+ },
+ "@meshtasticBusyTitle": {
+ "description": "Another app holds the BLE link"
+ },
+ "@windForecastCountyOutlineHint": {
+ "description": "Hint under the county-border toggle in the wind-forecast overlay menu."
+ },
+ "mapOverlaySectionReference": "參考圖層",
+ "mapLayerSatelliteB02": "ひまわり 可見光-綠(B02)",
+ "weatherRankingEmpty": "而家冇可排序嘅觀測",
+ "notifySectionOther": "其他",
+ "weatherRankingMeta": "資料時間:{time}\n共 {count} 觀測點",
+ "onboardingTermsAgree": "我已閱讀並同意服務條款",
+ "mapLayerSatelliteTransparentNoVegetation": "< 0.1 = 透明(無植被)",
+ "notifyOptLocalIntensity4": "所在地震度4以上",
+ "eewArrived": "已抵達",
+ "meshtasticNoDevices": "找唔到 Meshtastic 裝置",
+ "mapLayerCategoryLife": "生活",
+ "reportFilterSortIntensity": "震度",
+ "meshtasticStateDisconnected": "未連線",
+ "typhoonIntensityIntense": "強烈颱風",
+ "@meshtasticSend": {
+ "description": "Send message button"
+ },
+ "mapLayerOrderTitle": "調整圖層順序",
+ "@skyTimeNoon": {
+ "description": "Label for the skyTimeNoon option in the experimental backdrop settings."
+ },
+ "@meshtasticShortName": {
+ "description": "The radio's short name"
+ },
+ "dpmYes": "係",
+ "meshtasticNoHistory": "歷史紀錄還唔夠",
+ "reportDetailLocalIntensityUnavailable": "冇震度訊息",
+ "mapLayerWindForecastGfs": "GFS",
+ "reportFilterDepth": "深度",
+ "@meshtasticNoHistory": {
+ "description": "Chart placeholder before two samples exist"
+ },
+ "onboardingScrollHint": "向下捲動以繼續",
+ "@meshtasticRadio": {
+ "description": "Radio diagnostics sheet title"
+ },
+ "mapNavQpesums": "預報",
+ "@meshtasticStateError": {
+ "description": "Connection state label"
+ },
+ "@meshtasticVoltage": {
+ "description": "Battery voltage"
+ },
+ "notifyAdvisory": "天氣警告及特報",
+ "@meshtasticNoMessages": {
+ "description": "Empty message log while connected"
+ },
+ "reportFilterReset": "重設",
+ "mapLayerSatelliteMndwi": "ひまわり 改良水體指數",
+ "typhoonOverlaySectionStorm": "暴風圈",
+ "moonPhaseFull": "滿月",
+ "@meshtasticEmptyMessage": {
+ "description": "Placeholder for a text packet with no body"
+ },
+ "meshtasticBinaryPayload": "二進位內容 · {size}",
+ "@radarGlobalOutlineHint": {
+ "description": "Hint under the national-border toggle in the radar overlay menu."
+ },
+ "moonPhaseWaningGibbous": "虧凸月",
+ "reportFilterIntensityInfoModernTitle": "新制(2020 起)",
+ "@mapAppGoogleMaps": {},
+ "typhoonDataTime": "資料時間\n{time}",
+ "restroomTypeAccessible": "無障礙廁所",
+ "moreSectionAbout": "關於",
+ "meshtasticSelectDevice": "選擇裝置",
+ "onboardingIntroBody": "DPIP 係同你並肩嘅防災夥伴,整合強震即時警報、地震報告、天氣同各類災害資訊,喺關鍵時刻即時通知你。\n\n• 地震:強震即時警報、震度速報同地震報告\n• 天氣:雷暴即時訊息、天氣警告及特報\n• 海嘯同防災資訊\n\n接下來,我哋會請你閱讀服務條款,並授權幾項讓 DPIP 能即時守護你嘅權限。",
+ "shelterCapacityLabel": "收容人數",
+ "reportDetailImage": "地震報告圖",
+ "meshtasticStateConfiguring": "設定中…",
+ "@moonPhaseLastQuarter": {
+ "description": "Phase: last quarter"
+ },
+ "typhoonLabelGaleAvg": "七級風平均暴風半徑",
+ "onboardingPermNotify": "通知",
+ "meshtasticClearMessages": "清除訊息",
+ "meshtasticNotifyMessages": "新訊息通知",
+ "defaultMapLayerSettings": "地圖預設圖層",
+ "eewSourceSettings": "地震速報來源",
+ "eewSourceSubtitle": "選擇要顯示哪些機構發布嘅地震速報。",
+ "eewSourceAll": "所有來源",
+ "eewSourceAllDescription": "顯示所有機構發布嘅地震速報。",
+ "eewSourceCwaOnly": "僅中央氣象署",
+ "eewSourceCwaOnlyDescription": "只顯示中央氣象署發布嘅地震速報。",
+ "moreSectionNotify": "通知",
+ "@moonPhaseFull": {
+ "description": "Phase: full moon"
+ },
+ "notifyUnavailable": "推送尚未就緒,請稍後再試。",
+ "mapLayerOrderReset": "回復預設順序",
+ "weatherRankingMergeCounty": "縣市",
+ "moreSectionApp": "取得 App",
+ "moreSectionBeta": "測試版",
+ "moreAndroidBeta": "Android 測試版",
+ "moreTestFlight": "iOS 測試版(TestFlight)",
+ "moreSectionPartners": "合作夥伴",
+ "morePartnersNote": "依合作時間先後排列。感謝呢些個人同公司對防災嘅貢獻,佢哋讓 DPIP 成為可能。",
+ "morePartnerGeoscience": "巨科資訊有限公司",
+ "morePartnerTwds": "台灣數位串流有限公司",
+ "reportFilterIntensityInfoLegacyBody": "震度僅 0–7,冇 5弱/5強/6弱/6強。",
+ "mapLayerSatelliteSst": "ひまわり 海表溫度",
+ "qpesumsOverlayMenuTooltip": "定量降水預報圖層選項",
+ "@skyTimeAfternoon": {
+ "description": "Label for the skyTimeAfternoon option in the experimental backdrop settings."
+ },
+ "mapTimelineFuture": "未來",
+ "typhoonLegendCircleAvg": "平均圓",
+ "reportFilterDepthKm": "{depth} 公里",
+ "typhoonLabelSe": "東南側",
+ "radarTownOutlineHint": "較細嘅分區",
+ "eewCountdown": "{seconds} 秒",
+ "@meshtasticDisconnect": {
+ "description": "Disconnect from the radio"
+ },
+ "typhoonLabelGust": "瞬間最大陣風",
+ "mapAppGoogleMaps": "Google Maps",
+ "sponsorTerms": "使用條款",
+ "restroomTypeGenderNeutral": "性別友善廁所",
+ "@skyTimeDusk": {
+ "description": "Label for the skyTimeDusk option in the experimental backdrop settings."
+ },
+ "notifyThunderstorm": "雷暴即時訊息",
+ "skyTimeGolden": "黃金時刻",
+ "moonAge": "月齡",
+ "@windForecastTownOutlineHint": {
+ "description": "Hint under the township-border toggle in the wind-forecast overlay menu."
+ },
+ "meshtasticRadioSettings": "LoRa",
+ "@meshtasticNotifyMessages": {
+ "description": "Toggle: local notification for an incoming mesh message"
+ },
+ "moreGithub": "ExpTech GitHub",
+ "homeForecastUnavailable": "選擇地區後可查看預報",
+ "mapLayers": "圖層",
+ "meshtasticHardware": "硬體",
+ "languageSettings": "語言設定",
+ "@moonNextFullMoon": {
+ "description": "Next full moon date label"
+ },
+ "language": "語言",
+ "homeForecastFeelsLike": "體感 {temp}°",
+ "typhoonOverlayWeatherHint": "對齊報文時間",
+ "@meshtasticHopLimit": {
+ "description": "How many hops a packet may take"
+ },
+ "skyTimeDawn": "黎明",
+ "skyTimeAfternoon": "下午",
+ "meshtasticLastHeard": "最後聽到",
+ "typhoonWarningTitle": "颱風警報",
+ "moreSourceCode": "原始碼",
+ "mapLayerCategoryWeather": "氣象觀測",
+ "mapLayerSatelliteB09": "ひまわり 中層水氣(B09)",
+ "windForecastTownOutlineHint": "更細嘅網格",
+ "mapLayerSatelliteCloudmask": "ひまわり 雲遮罩",
+ "mapAppCopyCoordinates": "複製座標",
+ "reportFilterIntensityInfoIntro": "中央氣象署自 2020 年 1 月 1 日(臺北時間)起改用新制震度。",
+ "mapNavEarthquake": "地震",
+ "restroomGradeAverage": "普通級",
+ "@meshtasticNodes": {
+ "description": "Mesh nodes section header"
+ },
+ "mapLayerSatelliteBtdCo2": "ひまわり 卷雲/雲高",
+ "onboardingPermBackgroundDesc": "選擇「一律允許」,關閉 App 都能推送本地警報。",
+ "mapTimelineForecast": "預報",
+ "restroomTypeLabel": "廁所類型",
+ "navEarthquake": "地震",
+ "typhoonOverlayStormL10Tooltip": "十級暴風圈+平均圓(黃色)",
+ "moonPhaseWaxingGibbous": "盈凸月",
+ "reportDetailTitle": "地震報告",
+ "moreTremReport": "TREM 偵測報告",
+ "weatherDataTime": "{station} ∙ 資料時間 {time}",
+ "meshtasticNoNodes": "尚未聽到任何節點",
+ "meshtasticViaMqtt": "經 MQTT(網際網路)",
+ "radarCountyOutline": "縣市界線",
+ "@mapAppCopyCoordinates": {},
+ "commonClose": "關閉",
+ "restroomGradeLabel": "等級",
+ "rainIntervalNow": "今日",
+ "changelogCurrentVersion": "而家版本",
+ "typhoonOverlayForecastCalloutsTooltip": "放大時顯示預測點詳細卡片",
+ "typhoonLabelPressure": "中心氣壓",
+ "aedOpenRemark": "開放時間備註",
+ "onboardingPermsBody": "為咗喺災害發生嘅第一時間通知你,請授權以下權限。你隨時可以喺系統設定中更改。",
+ "typhoonOverlaySectionWeather": "天氣底圖",
+ "@meshtasticStateConnected": {
+ "description": "Connection state label"
+ },
+ "notifyOptWeatherLocal": "接收所在地",
+ "mapNavRain": "雨量",
+ "moonDays": "天",
+ "mapLegendUnit": "單位:{unit}",
+ "weatherModeClear": "晴天",
+ "meshtasticRadio": "電台",
+ "commonEmpty": "冇資料",
+ "mapLayerSatelliteB01": "ひまわり 可見光-藍(B01)",
+ "meshtasticExternalPower": "外部供電",
+ "moonPhaseLastQuarter": "下弦月",
+ "@meshtasticName": {
+ "description": "The radio's long name"
+ },
+ "reportFilterOrderAsc": "升序",
+ "reportFilterApply": "套用",
+ "reportDetailImageUnavailable": "報告圖尚未提供",
+ "@weatherModeSand": {
+ "description": "Label for the weatherModeSand option in the experimental backdrop settings."
+ },
+ "weatherRankingHighest": "最高",
+ "reportDetailReplay": "重播",
+ "mapLayerRestroom": "公廁",
+ "restroomCategoryWelfare": "社福機構、集會場所",
+ "restroomGradeExcellent": "特優級",
+ "meshtasticLastSent": "最近送出",
+ "meshtasticName": "名稱",
+ "meshtasticScan": "掃描",
+ "@radarOverlayMenuTooltip": {
+ "description": "Tooltip for the radar overlay-options chip beside the layer switcher"
+ },
+ "mapLayerCategoryForecast": "數值預報",
+ "meshtasticChannelFailed": "冇辦法設定 DPIP 頻道",
+ "themeSystem": "跟隨系統",
+ "mapLayerSatelliteNdvi": "ひまわり 植生指數",
+ "typhoonLegendForecast": "預測路徑",
+ "typhoonValueHpa": "{n} 百帕",
+ "weatherPrecipitation": "降水量",
+ "moonNextFullMoon": "下次滿月",
+ "dpmSheetEmpty": "點選地圖上嘅標記查看詳情",
+ "onboardingSkipLeave": "仍要略過",
+ "aedPlaceDesc": "放置位置講明",
+ "@weatherModeOvercast": {
+ "description": "Label for the weatherModeOvercast option in the experimental backdrop settings."
+ },
+ "onboardingSkipTitle": "尚未完成授權",
+ "restroomTypeFamily": "親子廁所",
+ "typhoonValueKm": "{n} 公里",
+ "@radarCountyOutlineSubtitle": {
+ "description": "County-border overlay toggle in the map's radar overlay menu."
+ },
+ "@meshtasticCopied": {
+ "description": "Toast shown after copying a message"
+ },
+ "onboardingPermBattery": "省電白名單",
+ "typhoonLabelNw": "西北側",
+ "moonPhaseWaxingCrescent": "眉月",
+ "restroomCategoryLeisure": "休閒娛樂場所",
+ "mapLayerTemperature": "溫度",
+ "aedCategory": "場所分類",
+ "@moonTimelineCaption": {
+ "description": "Moon phase timeline caption"
+ },
+ "meshtasticChannels": "頻道",
+ "monitorWaiting": "等待資料…",
+ "typhoonOverlayForecastCallouts": "預測點資訊",
+ "@meshtasticTitle": {
+ "description": "Meshtastic test page title"
+ },
+ "reportDetailEpicenter": "震央座標",
+ "meshtasticVoltage": "電壓",
+ "mapLayerMeshtasticSubtitle": "電台聽到過嘅 LoRa 網狀網路節點",
+ "@meshtasticSent": {
+ "description": "Packets sent this session"
+ },
+ "mapLayerWind": "風向",
+ "reportDetailMagnitude": "地震規模",
+ "@meshtasticRole": {
+ "description": "Device role (client, router...)"
+ },
+ "reportDetailAreaIntensity": "各地震度",
+ "rainInterval12h": "12 時",
+ "reportListMagnitude": "M{magnitude}",
+ "notifyMonitor": "強震監視器",
+ "onboardingStart": "開始使用",
+ "@meshtasticExternalPower": {
+ "description": "Battery value when mains powered"
+ },
+ "@skyTime": {
+ "description": "Label for the experimental sky time-of-day override."
+ },
+ "sponsorPerMonth": "{price} / 月",
+ "mapLayerPressure": "氣壓",
+ "@radarTownOutlineSubtitle": {
+ "description": "Township-border overlay toggle in the map's radar overlay menu."
+ },
+ "mapLayerSatelliteB04": "ひまわり 近紅外(B04)",
+ "mapLayerSatelliteTransparentZero": "零差值 = 透明(無訊號)",
+ "shelterIndoorLabel": "室內收容",
+ "notifyOptOff": "關閉",
+ "reportFilterSortTime": "時間",
+ "mapLayerSatelliteCloudProbablyClear": "可能晴空",
+ "weatherModeThunderstorm": "雷暴",
+ "homeViewOnMap": "前往地圖查看",
+ "reportFilterIntensityInfoLegacyTitle": "舊制(2020 以前)",
+ "typhoonLabelSpeed": "過去移動時速",
+ "@meshtasticReconnecting": {
+ "description": "The link dropped and is being re-established"
+ },
+ "mapAppOpenFailed": "冇辦法開啟 {app}",
+ "mapLayerSatelliteRgbComposite": "RGB 合成(JMA 配方)",
+ "@meshtasticStateDisconnected": {
+ "description": "Connection state label"
+ },
+ "meshtasticReceived": "已接收",
+ "weatherRankingExtremeLow": "今日最低",
+ "@meshtasticRegionSwitch": {
+ "description": "Button applying the DPIP LoRa region"
+ },
+ "mapLayerSatelliteB10": "ひまわり 低層水氣(B10)",
+ "mapLayerSatelliteCloudProbablyCloudy": "可能有雲",
+ "shelterCategoryLabel": "適用災害",
+ "mapLayerSatelliteTransparentNoWater": "≤ 0 = 透明(無水體)",
+ "meshtasticStateConnecting": "連線中…",
+ "moonTitle": "月亮",
+ "weatherRankingGust": "陣風",
+ "moreAppStore": "App Store",
+ "@meshtasticUndecoded": {
+ "description": "Packets the radio could not decrypt"
+ },
+ "@commonCancel": {
+ "description": "Dismisses a dialog without acting"
+ },
+ "moreServerStatus": "伺服器狀態",
+ "notifySectionWeather": "天氣",
+ "meshtasticPreset": "調變預設",
+ "dataSectionSeismic": "地震",
+ "changelogBodyEmpty": "此版本冇講明。",
+ "changelogOpenOnGitHub": "喺 GitHub 查看",
+ "radarGlobalOutline": "國界",
+ "notifyEew": "緊急地震速報",
+ "regionNationwide": "全國",
+ "moreNotifyLog": "DPIP 通知發送記錄",
+ "regionCurrent": "所在地",
+ "meshtasticNotConnected": "尚未連線至裝置",
+ "weatherModeSnow": "下雪",
+ "mapLayerMeshtastic": "Meshtastic 節點",
+ "moreDeveloper": "偵錯資訊",
+ "@qpesumsOverlayMenuTooltip": {
+ "description": "Tooltip for the QPESUMS forecast overlay-options chip beside the layer switcher."
+ },
+ "mapLayerSatelliteB14": "ひまわり 長波紅外線(B14)",
+ "meshtasticChannelUse": "頻道使用率",
+ "mapNavLightning": "閃電",
+ "homeForecastEmpty": "而家冇預報資料",
+ "sponsorOneTime": "單次支援",
+ "mapLayerSatelliteBtdSplit": "ひまわり 分割視窗",
+ "onboardingPermBackground": "背景定位",
+ "aedEmergencyPhone": "緊急聯絡電話",
+ "dpmOpenInMaps": "開啟地圖",
+ "meshtasticNotifyNodes": "新節點通知",
+ "onboardingPermCriticalDesc": "讓危及生命嘅強震即時警報,即使喺靜音或勿擾模式下都能發出聲響。",
+ "@mapAppDefault": {
+ "placeholders": {
+ "app": {
+ "type": "String"
+ }
+ }
+ },
+ "mapLayerSatelliteTransparentWarm": "晴空(暖端) = 透明,顯示底圖",
+ "meshtasticSent": "已送出",
+ "homeForecastTitle": "24小時預報",
+ "typhoonLegendWarningAreas": "警報區域",
+ "meshtasticExcludeMqttHidden": "已隱藏 {count} 個",
+ "notifyOptLocalIntensity1": "所在地震度1以上",
+ "@skyTimeGolden": {
+ "description": "Label for the skyTimeGolden option in the experimental backdrop settings."
+ },
+ "@meshtasticChannelReady": {
+ "description": "The DPIP channel exists on the radio"
+ },
+ "mapTimelinePast": "歷史",
+ "restroomTypeFemale": "女廁所",
+ "reportListToday": "今天",
+ "meshtasticTapNode": "點選節點查看詳細資訊",
+ "commonLoading": "載入中…",
+ "@meshtasticStateConnecting": {
+ "description": "Connection state label"
+ },
+ "typhoonIntensityModerate": "中度颱風",
+ "mapLayerSatelliteAsh": "ひまわり 火山灰",
+ "rainInterval3h": "3 時",
+ "meshtasticChannelReady": "DPIP 頻道已就緒",
+ "@meshtasticNotifyNodes": {
+ "description": "Toggle: local notification when a new node is heard"
+ },
+ "mapLayerCategorySatellite": "衛星",
+ "mapLayerSatelliteNightmicrophysics": "ひまわり 夜間微物理",
+ "typhoonIntensityTd": "熱帶性低氣壓",
+ "reportFilterDate": "日期",
+ "sponsorRestoreUnavailable": "冇辦法連線至商店,請稍後再試",
+ "homeForecastPop": "{pop}%",
+ "regionEmpty": "尚未新增常用地區",
+ "@radarScanRangeSubtitle": {
+ "description": "Radar scan-range overlay toggle in the map's radar overlay menu."
+ },
+ "@moonAge": {
+ "description": "Moon age label"
+ },
+ "onboardingPermBatteryDesc": "允許 DPIP 喺背景持續運作,避免警報延遲或漏收。",
+ "onboardingPermUnusedApp": "保持 App 啟用",
+ "onboardingPermUnusedAppDesc": "Android 會暫停你長期未開啟嘅 App 並撤銷佢哋嘅權限,噉會令災害警報冇辦法送到你所在地。",
+ "onboardingPermBackgroundExec": "背景執行",
+ "onboardingPermBackgroundExecDesc": "關閉時,App 唔會被喚醒回報你嘅位置。",
+ "onboardingPermVendorPower": "手機廠商省電設定",
+ "onboardingPermVendorPowerDesc": "{brand} 會停止你最近冇開過嘅 App 嘅背景作業。App 冇辦法偵測或變更,請手動允許。",
+ "mapNavDisaster": "防災",
+ "radarScanRangeSubtitle": "標示四座雷達實際觀測到嘅範圍。",
+ "aedHoursSunday": "週日開放時間",
+ "reportDetailOriginTime": "發震時間",
+ "trendNoData": "冇趨勢資料",
+ "onboardingPermLocation": "定位",
+ "moreDiscord": "Discord 社群",
+ "mapNavPressure": "氣壓",
+ "mapLayerSatelliteB13": "ひまわり 紅外線(B13)",
+ "typhoonTdNo": "TD {no}",
+ "changelogEmpty": "而家冇更新日誌",
+ "@skyTimeDawn": {
+ "description": "Label for the skyTimeDawn option in the experimental backdrop settings."
+ },
+ "@meshtasticViaMqtt": {
+ "description": "Legend: node reported over an MQTT bridge"
+ },
+ "reportFilterDateStartNote": "開始日:當日 00:00(台北時間)",
+ "eewTitle": "地震速報",
+ "mapLayerWindForecastEcmwf": "ECMWF",
+ "regionSelectCount": "已選 {count}/{max}",
+ "@meshtasticRegionMismatch": {
+ "description": "Radio is on another LoRa region than DPIP needs",
+ "placeholders": {
+ "region": {
+ "type": "String"
+ }
+ }
+ },
+ "mapLayerSatelliteBtdSo2": "ひまわり 二氧化硫/雲相",
+ "meshtasticStateError": "錯誤",
+ "weatherModeOvercast": "陰天",
+ "@meshtasticScan": {
+ "description": "Start scanning for Meshtastic radios"
+ },
+ "reportDetailDepth": "震源深度",
+ "typhoonOverlayWarningTooltip": "標示警報區域縣市",
+ "reportFilterDatePick": "選擇日期",
+ "onboardingSkipStay": "返回授權",
+ "@moonPhaseWaxingCrescent": {
+ "description": "Phase: waxing crescent"
+ },
+ "@meshtasticOnline": {
+ "description": "Legend: node heard within the online window"
+ },
+ "commonFetchFailed": "冇辦法獲取資料,請稍後重試",
+ "@meshtasticTxPower": {
+ "description": "Transmit power"
+ },
+ "shelterOutdoorLabel": "室外收容",
+ "meshtasticStateConnected": "已連線",
+ "mapNavRadar": "雷達",
+ "mapLayerSatelliteCloudClear": "晴空",
+ "eewSummary": "規模 {magnitude}・深度 {depth} 公里",
+ "locationBannerPermission": "尚未授權定位,冇辦法針對你嘅所在地推送警報。",
+ "typhoonOverlayWeatherNoneTooltip": "唔疊雷達或紅外線",
+ "radarCountyOutlineHint": "畫喺回波上面",
+ "windForecastCountyOutlineHint": "繪製喺風場上面",
+ "homeRainTrendTitle": "近 1 小時降水趨勢",
+ "moonPhaseFirstQuarter": "上弦月",
+ "mapLayerCategoryTyphoon": "颱風",
+ "@windForecastOverlayMenuTooltip": {
+ "description": "Tooltip for the wind-forecast overlay-options chip beside the layer switcher."
+ },
+ "@meshtasticNodeId": {
+ "description": "The radio's node number"
+ },
+ "meshtasticUtilization": "空中工時(24 小時)",
+ "restroomTypeMixed": "混合廁所",
+ "restroomGradeGood": "優等級",
+ "notifyTsunami": "海嘯資訊",
+ "navData": "資料",
+ "mapLayerSatelliteBtdWvirw": "ひまわり 過衝雲頂",
+ "meshtasticReadingAge": "數值時間",
+ "@moonPhaseWaningGibbous": {
+ "description": "Phase: waning gibbous"
+ },
+ "mapAppCallFailed": "此裝置冇辦法撥打電話",
+ "@meshtasticPower": {
+ "description": "Section: battery and uptime"
+ },
+ "reportFilterAny": "唔限",
+ "weatherRankingMergeTo": "合併至",
+ "notifyIntensity": "震度速報",
+ "rainIntervalMenu": "累積時段",
+ "reportDetailLocalFelt": "小區域有感地震",
+ "meshtasticDevice": "裝置",
+ "onboardingGrant": "授權",
+ "weatherModeRain": "雨天",
+ "shelterVulnerableOkLabel": "適合避難弱者安置",
+ "stationSheetEmpty": "點選任一測站查看觀測值",
+ "typhoonLegendProbability": "侵襲機率",
+ "@meshtasticExcludeMqtt": {
+ "description": "Toggle hiding internet-bridged nodes"
+ },
+ "@radarScanRangeHint": {
+ "description": "Hint under the radar scan-range toggle in the radar overlay menu."
+ },
+ "reportFilterMagnitude": "規模",
+ "skyTimeMorning": "上午",
+ "@meshtasticNoDevices": {
+ "description": "Empty scan result"
+ },
+ "experimentalFeatures": "實驗性功能",
+ "onboardingTermsBody": "使用 DPIP 前,請詳閱以下注意事項:\n\n• 任何資訊應以中央氣象署發布嘅內容為準。\n\n• 根據網絡狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收唔到資訊嘅可能性,我哋會盡力避免此類情況,但唔保證一定唔會發生。\n\n• 強烈搖晃有機會早過通知到達用戶所在地。\n\n• 地震速報係快速計算嘅結果,可能存在較大誤差,應該理解並謹慎使用。\n\n• 任何唔受官方認可嘅行為均有可能承擔法律風險,請務必遵守相關規範。\n\n此外,為提供本地化警報,本服務會喺前景及背景收集並上傳你嘅概略位置同裝置推送識別碼,僅用嚟決定應向你推送嘅警報。\n\n㩒下方「同意並繼續」就表示你已閱讀、理解並同意上述事項。",
+ "reportFilterTitle": "篩選",
+ "onboardingPermCritical": "重大通知",
+ "trendCumulativeTotal": "累計 {total} mm",
+ "reportListEmptyFiltered": "冇符合條件嘅地震報告",
+ "meshtasticExcludeMqtt": "隱藏 MQTT 節點",
+ "mapNavTyphoon": "颱風",
+ "weatherModeSand": "沙塵",
+ "@moonPhaseFirstQuarter": {
+ "description": "Phase: first quarter"
+ },
+ "@dpmOpenInMaps": {},
+ "notifyReport": "地震報告",
+ "mapAppCoordinatesCopied": "已複製座標",
+ "skyTimeNight": "夜晚",
+ "sponsorRecommended": "推薦",
+ "mapLayerSatelliteB15": "ひまわり 長波紅外線(B15)",
+ "weatherRankingWind": "風速",
+ "feedStale": "資料可能已過期",
+ "homeForecastWind": "{direction} · {level} 級",
+ "navHome": "主頁",
+ "meshtasticRegionLabel": "地區",
+ "mapLayerSatelliteCloudtop": "ひまわり 雲頂溫度",
+ "moonTimelineCaption": "月相",
+ "@meshtasticChannelNoSlot": {
+ "description": "Every secondary channel slot is taken"
+ },
+ "@meshtasticBusyBody": {
+ "description": "Why two clients on one radio is a problem"
+ },
+ "openSourceLicenses": "引用套件",
+ "weatherRankingLowest": "最低",
+ "@meshtasticConnectAnyway": {
+ "description": "Connect despite the other app"
+ },
+ "reportFilterSortDepth": "深度",
+ "mapTimelineDataTime": "資料時間 {time}",
+ "radarScanRange": "顯示掃描範圍",
+ "meshtasticHopLimit": "跳數上限",
+ "@meshtasticUptime": {
+ "description": "Time since the radio booted"
+ },
+ "weatherRankingExtremeHigh": "今日最高",
+ "@meshtasticUtilization": {
+ "description": "Section title for the 24h airtime chart"
+ },
+ "sponsorPrivacy": "私隱權政策",
+ "reportDetailLocalIntensity": "所在地嘅震度",
+ "mapLayerSatelliteNaturalcolor": "ひまわり 自然色",
+ "meshtasticAirtime": "發射佔空比",
+ "shelterCapacityValue": "{n} 人",
+ "lightningLegendCc": "雲間 · {minutes} 分內",
+ "meshtasticSendHint": "要廣播嘅訊息",
+ "monitorDelay": "延遲 {value} s",
+ "@meshtasticFirmware": {
+ "description": "Firmware version"
+ },
+ "dpmNo": "否",
+ "mapLayerSatelliteB08": "ひまわり 上層水氣(B08)",
+ "meshtasticReconnecting": "重新連線中…",
+ "@mapAppAppleMaps": {},
+ "@meshtasticReadingAge": {
+ "description": "How old the battery/airtime numbers are"
+ },
+ "radarTownOutlineSubtitle": "讓鄉鎮界線在雷達回波下仍然清楚。",
+ "@moonPhaseWaxingGibbous": {
+ "description": "Phase: waxing gibbous"
+ },
+ "typhoonOverlayWeatherSatelliteTooltip": "紅外線(對齊颱風報文時間)",
+ "radarScanRangeHint": "框外空白代表未觀測",
+ "typhoonPickerTd": "熱帶性低氣壓 TD {no}",
+ "mapLayerSatelliteWatervapor": "ひまわり 水氣",
+ "regionAddButton": "新增地區",
+ "displaySettings": "顯示設定",
+ "restroomGradePoor": "唔合格",
+ "restroomCategoryTourist": "觀光地區及風景區",
+ "locationBannerServiceOff": "定位服務已關閉,冇辦法針對你嘅所在地推送警報。",
+ "mapLayerStyleTooltip": "顯示樣式",
+ "lightningLegendCg": "對地 · {minutes} 分內",
+ "skyTimeAuto": "自動",
+ "appLogs": "App 日誌",
+ "serverStatusLocal": "本機狀態",
+ "serverStatusLocalBody": "伺服器指標來自控制台。下方係本機對多活端點(LB / Core 各區)嘅實際連線判斷:APP 只被動記錄本機實際播送嘅流量,若該端點從未被本機觸發,就會顯示未探測。",
+ "serverStatusAllUp": "所有服務正常",
+ "serverStatusDegraded": "服務效能下降",
+ "serverStatusDown": "服務異常",
+ "serverStatusErrorRate": "5xx 錯誤率",
+ "serverStatusLatency": "平均延遲",
+ "serverStatusUpdated": "更新於",
+ "serverStatusWeb": "伺服器狀態",
+ "serverStatusWebUrl": "status.exptech.dev",
+ "serverStatusExpTech": "ExpTech 狀態",
+ "serverStatusCloudflare": "Cloudflare 狀態",
+ "serverStatusCloudflareAllOperational": "所有區域正常",
+ "serverStatusCloudflareOutage": "Cloudflare 部分區域異常",
+ "serverStatusCloudflareNone": "而家冇可顯示嘅區域。",
+ "serverStatusCloudflareOperational": "正常",
+ "serverStatusCloudflareDegraded": "效能下降",
+ "serverStatusCloudflarePartial": "部分中斷",
+ "serverStatusCloudflareMajor": "大規模中斷",
+ "serverStatusCloudflareUnknown": "未知",
+ "endpointTierLbApi": "LB API",
+ "endpointTierLbStatic": "LB Static",
+ "endpointTierCoreApi": "Core API",
+ "endpointTierCoreStatic": "Core Static",
+ "endpointTierCoreExclusiveApi": "Core 專屬 API(雷達 / 氣象 / 風場)",
+ "endpointTierCoreStaticExclusive": "Core 專屬靜態資源",
+ "endpointTierLegacyApi": "舊版 API(api-1)",
+ "endpointHealthOk": "本機連線正常",
+ "endpointHealthDegraded": "有端點連線唔穩",
+ "endpointHealthDown": "本機連線異常",
+ "endpointHealthUnknown": "尚無觀測資料",
+ "endpointStateOk": "正常",
+ "endpointStateDegraded": "唔穩",
+ "endpointStateDown": "異常",
+ "endpointStateUnknown": "未知",
+ "endpointServiceEew": "地震速報",
+ "endpointServiceRts": "強震即時警報",
+ "endpointServiceRadar": "雷達",
+ "endpointServiceSatellite": "衛星",
+ "endpointServiceQpesums": "定量降水",
+ "endpointServiceWind": "風場",
+ "endpointServiceDpm": "災害點位",
+ "endpointServiceWeather": "天氣",
+ "endpointServiceRain": "降雨",
+ "endpointServiceLightning": "閃電",
+ "endpointServiceTyphoon": "颱風",
+ "endpointServiceReport": "地震報告",
+ "endpointServiceTremStation": "震度站",
+ "endpointServiceEvent": "事件",
+ "endpointServiceLocation": "定位",
+ "endpointServiceNotify": "通知",
+ "endpointServiceOther": "其他",
+ "feedConnecting": "連接中…",
+ "notifyBannerDisabled": "通知已關閉,將收唔到災害警報。",
+ "@meshtasticNoNodes": {
+ "description": "Empty node list"
+ },
+ "weatherHumidity": "濕度",
+ "typhoonValueMs": "每秒 {n} 公尺",
+ "homeForecastHumidity": "濕度 {value}%",
+ "meshtasticBusyBody": "請先喺另一個 Meshtastic App 中斷線。兩個 App 同時連同一台裝置會互相搶走訊息,導致部分訊息遺失。",
+ "meshtasticChannelNoSlot": "冇可用嘅頻道空位 — 請先喺裝置上空出一個",
+ "restroomCategoryTransport": "交通",
+ "meshtasticBattery": "電量",
+ "meshtasticDistance": "距離",
+ "meshtasticSnrTrend": "訊號趨勢 (SNR)",
+ "meshtasticBatteryTrend": "電量趨勢",
+ "typhoonOverlayMenuTooltip": "颱風圖層選項",
+ "mapLayerSatelliteBtdOzone": "ひまわり 對流層頂",
+ "meshtasticRegionMismatch": "裝置地區為 {region} — DPIP 需要 TW",
+ "notifySectionEarthquake": "地震",
+ "mapLayerDisasterMap": "防災地圖",
+ "weatherModeFog": "大霧",
+ "typhoonPickerNamed": "{name} TY {no}",
+ "mapLayerStyleGrayTooltip": "氣象廳灰階慣例:溫度越低越白",
+ "moreAnnouncements": "公告",
+ "moreTagline": "防災資訊整合平台",
+ "moreVersionStable": "正式版",
+ "moreVersionNotes": "本次更新",
+ "moreVersionNotesHighlightsSubtitle": "呢個版本做咗哪些改變",
+ "releaseHighlightsSeeNotes": "查看完整更新日誌",
+ "releaseHighlightsTitle": "{train} 重點整理",
+ "releaseHighlightsTabNormal": "做咗哪些改變",
+ "releaseHighlightsTabAdvanced": "深入技術",
+ "releaseHighlightsEmpty": "而家冇內容。",
+ "moreVersionNotesEmpty": "找唔到而家版本嘅更新日誌",
+ "moreVersionSnapshot": "測試版",
+ "mapLayerSatelliteTransparentNoData": "無資料(陸地) = 透明",
+ "@meshtasticScanning": {
+ "description": "Scan in progress"
+ },
+ "restroomCategoryGovernment": "民眾洽公場所",
+ "typhoonLegendCurrent": "而家中心",
+ "aedAddress": "地址",
+ "mapLayerAed": "AED",
+ "changelogTypePrerelease": "測試版",
+ "reportFilterIntensityInfoModernBody": "震度為 0–4、5弱、5強、6弱、6強、7。篩選滑桿依新制;列表中較早嘅地震會以舊制標示顯示。",
+ "typhoonOverlayWeatherNone": "無",
+ "mapLayerStyleGray": "灰階(JMA)",
+ "weatherModeAuto": "自動",
+ "typhoonLabelProbCircle": "70%機率圓",
+ "@radarCountyOutline": {
+ "description": "County-border overlay toggle in the map's radar overlay menu."
+ },
+ "notifyOptAll": "接收全部",
+ "displayTheme": "主題",
+ "mapLayerSatelliteB07": "ひまわり 短波紅外(B07)",
+ "@skyTimeSunrise": {
+ "description": "Label for the skyTimeSunrise option in the experimental backdrop settings."
+ },
+ "typhoonLabelDirection": "過去移動方向",
+ "@meshtasticLastSent": {
+ "description": "Age of the last sent packet"
+ },
+ "regionManageTitle": "常用地區",
+ "regionSaveNote": "通知係以 GPS 所在地位置發送嘅,設定常用地區唔會改變或影響通知發送,常用地區只係用於首頁快速查看唔同區域狀態,所以務必授予 GPS 定位權限,否則通知冇辦法運作",
+ "@regionSaveNote": {
+ "description": "常用地區與通知發送機制的說明"
+ },
+ "typhoonLegendCone": "預測圓錐",
+ "moreCwaEew": "中央氣象署強震即時警報",
+ "onboardingPermsTitle": "權限授權",
+ "mapLayerStyleJma": "雲頂強調(JMA)",
+ "rainInterval10m": "10 分",
+ "meshtasticConnectAnyway": "仍要連線",
+ "reportListDayCount": "{count}",
+ "mapLayerSatelliteB06": "ひまわり 近紅外(B06)",
+ "mapLayerSatelliteTransparentReflectance": "低反射率/夜間 = 透明,顯示底圖",
+ "chartHourLabel": "{hour}時",
+ "mapLayerShelter": "避難收容場所",
+ "typhoonOverlayProbabilityTooltip": "顯示侵襲機率(會隱藏預測圓錐)",
+ "mapLayerSatelliteNdwi": "ひまわり 水體指數",
+ "disasterMapOverlayShelterTooltip": "顯示避難收容場所",
+ "mapNavHumidity": "濕度",
+ "@meshtasticTraffic": {
+ "description": "Section: packet counters"
+ },
+ "reportDetailSortByIntensity": "依震度排序",
+ "homeRainTrendNoData": "無資料",
+ "mapLayerCategoryRadar": "雷達",
+ "meshtasticShortName": "簡稱",
+ "@meshtasticStateConfiguring": {
+ "description": "Connection state label"
+ },
+ "mapLayerSatelliteAirmass": "ひまわり 氣團",
+ "@meshtasticPreset": {
+ "description": "LoRa modem preset"
+ },
+ "dataSectionWeather": "氣象",
+ "aedHoursWeekday": "平日開放時間",
+ "homeActiveEventsTitle": "生效中事件",
+ "faq": "常見問題",
+ "eewSerial": "第 {serial} 報",
+ "@radarTownOutline": {
+ "description": "Township-border overlay toggle in the map's radar overlay menu."
+ },
+ "reportFilterSort": "排序方式",
+ "@skyTimeMorning": {
+ "description": "Label for the skyTimeMorning option in the experimental backdrop settings."
+ },
+ "meshtasticRegionConfirm": "要將呢台裝置切換為 TW 地區嗎?裝置會重新啟動並短暫斷線,上面嘅其他頻道都會一齊改變。",
+ "dataEarthquakeSubtitle": "地震報告",
+ "typhoonNoActive": "而家無颱風",
+ "@meshtasticExcludeMqttHidden": {
+ "description": "How many nodes the filter is hiding",
+ "placeholders": {
+ "count": {
+ "type": "int"
+ }
+ }
+ },
+ "mapLayerSatelliteB11": "ひまわり 二氧化硫/雲相(B11)",
+ "navEvents": "事件",
+ "onboardingTermsTitle": "服務條款",
+ "@meshtasticChannels": {
+ "description": "Section: the radio's channel table"
+ },
+ "mapOsmOverlay": "詳細地圖",
+ "mapOsmOverlayHint": "顯示更完整嘅道路、建物同地名",
+ "mapOsmDetails": "詳細設定",
+ "moreDataSources": "資料來源",
+ "dataSourceTremNet": "探索智慧科技有限公司 — TREM-Net",
+ "dataSourceCwa": "交通部中央氣象署 (CWA)",
+ "dataSourceJma": "気象庁 (JMA)",
+ "dataSourceNcdr": "國家災害防救科技中心 (NCDR)",
+ "dataSourceEcmwf": "European Centre for Medium-Range Weather Forecasts (ECMWF)",
+ "dataSourceNoaaGfs": "National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)",
+ "dataSourceGovernmentOpenData": "政府資料開放平臺",
+ "dataSourceOpenStreetMap": "© OpenStreetMap contributors",
+ "dataSourceNasaMoon": "National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)",
+ "mapOsmDetailsHint": "已啟用 {enabled} / 共 {total} 個圖層",
+ "@mapOsmDetailsHint": {
+ "description": "How many of the OSM layers are enabled",
+ "placeholders": {
+ "enabled": {
+ "type": "int"
+ },
+ "total": {
+ "type": "int"
+ }
+ }
+ },
+ "mapOsmSurface": "地表",
+ "mapOsmParks": "公園",
+ "mapOsmLandUse": "土地利用",
+ "mapOsmAirportAreas": "機場區域",
+ "mapOsmWater": "水域",
+ "mapOsmRivers": "河川",
+ "mapOsmBoundaries": "邊界",
+ "mapOsmBuildings": "建物",
+ "mapOsmRoads": "道路",
+ "mapOsmRoadNames": "道路名稱",
+ "mapOsmWaterNames": "水域名稱",
+ "mapOsmPeaks": "山峰",
+ "mapOsmAirportNames": "機場名稱",
+ "mapOsmPlaceNames": "地名",
+ "mapOsmPoi": "地標",
+ "mapOsmHouseNumbers": "門牌號碼",
+ "mapOsmRestoreAll": "全部恢復",
+ "mapOsmSectionNatural": "地表同自然",
+ "mapOsmSectionRoadsAndBuildings": "道路同建物",
+ "mapOsmSectionLabelsAndPlaces": "地名同標示",
+ "mapTownLabels": "鄉鎮名稱",
+ "notifySetFailed": "設定失敗,請稍後再試。",
+ "meshtasticDisconnect": "斷線",
+ "meshtasticUndecoded": "冇辦法解密",
+ "notifyAnnouncement": "公告",
+ "onboardingIntroTitle": "歡迎使用 DPIP",
+ "regionCurrentUnavailable": "冇辦法取得所在地位置資訊",
+ "languageSystem": "系統預設",
+ "skyTimeSunset": "日落",
+ "mapLayerSatelliteDust": "ひまわり 沙塵",
+ "mapAppAppleMaps": "Apple Maps",
+ "regionEdit": "修改",
+ "weatherDynamicState": "天氣動態狀態",
+ "moonNow": "而家",
+ "@moonNow": {
+ "description": "Returns the moon page to the present moment"
+ },
+ "moonSectionAppearance": "外觀",
+ "@moonSectionAppearance": {
+ "description": "Section header: how the Moon looks at the chosen moment"
+ },
+ "moonSectionRiseSet": "月出月落",
+ "@moonSectionRiseSet": {
+ "description": "Section header: moonrise and moonset for the user's township"
+ },
+ "moonSectionUpcoming": "接下來",
+ "@moonSectionUpcoming": {
+ "description": "Section header: the next full and new moons"
+ },
+ "moonSectionCalendar": "月曆",
+ "@moonSectionCalendar": {
+ "description": "Section header: the month-at-a-glance phase calendar"
+ },
+ "moonDistance": "距離",
+ "@moonDistance": {
+ "description": "Earth-Moon centre-to-centre distance"
+ },
+ "moonKilometres": "公里",
+ "@moonKilometres": {
+ "description": "Unit suffix for the lunar distance"
+ },
+ "moonApparentSize": "視直徑",
+ "@moonApparentSize": {
+ "description": "The Moon's apparent angular diameter"
+ },
+ "moonRise": "月出",
+ "@moonRise": {
+ "description": "Time the Moon rises"
+ },
+ "moonSet": "月落",
+ "@moonSet": {
+ "description": "Time the Moon sets"
+ },
+ "moonNextNewMoon": "下次新月",
+ "@moonNextNewMoon": {
+ "description": "Date and time of the next new moon"
+ },
+ "moonAlwaysUp": "整日在地平線上",
+ "@moonAlwaysUp": {
+ "description": "Shown when the Moon neither rises nor sets and stays above the horizon"
+ },
+ "moonNoEvent": "當日無",
+ "@moonNoEvent": {
+ "description": "Shown when a calendar day has no moonrise or no moonset"
+ },
+ "sunTitle": "太陽",
+ "@sunTitle": {
+ "description": "Sun page title"
+ },
+ "sunSectionDaylight": "日照",
+ "@sunSectionDaylight": {
+ "description": "Section header: sunrise, noon, sunset, day length"
+ },
+ "sunSectionTwilight": "曙暮光",
+ "@sunSectionTwilight": {
+ "description": "Section header: the three twilight bands"
+ },
+ "sunSectionLight": "光線",
+ "@sunSectionLight": {
+ "description": "Section header: golden and blue hour"
+ },
+ "sunSectionSundial": "日晷",
+ "@sunSectionSundial": {
+ "description": "Section header: equation of time and the next solar term"
+ },
+ "sunSectionTerms": "節氣",
+ "@sunSectionTerms": {
+ "description": "Section header: the year's twenty-four solar terms"
+ },
+ "sunRise": "日出",
+ "@sunRise": {
+ "description": "Time the Sun rises"
+ },
+ "sunSet": "日冇",
+ "@sunSet": {
+ "description": "Time the Sun sets"
+ },
+ "sunNoon": "正午",
+ "@sunNoon": {
+ "description": "Solar noon, the Sun's upper transit"
+ },
+ "sunDayLength": "白晝長度",
+ "@sunDayLength": {
+ "description": "How long the Sun is above the horizon, as hours:minutes"
+ },
+ "sunTwilightCivil": "民用",
+ "@sunTwilightCivil": {
+ "description": "Civil twilight, the Sun 6 degrees below the horizon"
+ },
+ "sunTwilightNautical": "航海",
+ "@sunTwilightNautical": {
+ "description": "Nautical twilight, 12 degrees below"
+ },
+ "sunTwilightAstronomical": "天文",
+ "@sunTwilightAstronomical": {
+ "description": "Astronomical twilight, 18 degrees below"
+ },
+ "sunGoldenHourMorning": "晨間黃金時刻",
+ "@sunGoldenHourMorning": {
+ "description": "Morning golden hour span"
+ },
+ "sunGoldenHourEvening": "昏間黃金時刻",
+ "@sunGoldenHourEvening": {
+ "description": "Evening golden hour span"
+ },
+ "sunBlueHour": "藍調時刻",
+ "@sunBlueHour": {
+ "description": "Blue hour span after sunset"
+ },
+ "sunEquationOfTime": "均時差",
+ "@sunEquationOfTime": {
+ "description": "Apparent solar time minus mean solar time"
+ },
+ "sunMinutes": "分",
+ "@sunMinutes": {
+ "description": "Unit suffix for the equation of time"
+ },
+ "solarTermNext": "下一個節氣",
+ "@solarTermNext": {
+ "description": "The next of the twenty-four solar terms"
+ },
+ "planetsTitle": "行星",
+ "@planetsTitle": {
+ "description": "Planets page title"
+ },
+ "planetsSectionTonight": "此刻",
+ "@planetsSectionTonight": {
+ "description": "Section header: the planets right now"
+ },
+ "planetUp": "地平線上",
+ "@planetUp": {
+ "description": "Badge: the planet is above the horizon"
+ },
+ "planetDown": "地平線下",
+ "@planetDown": {
+ "description": "Badge: the planet is below the horizon"
+ },
+ "planetInGlare": "太近太陽",
+ "@planetInGlare": {
+ "description": "Badge: too close to the Sun to be seen"
+ },
+ "planetMagnitude": "亮度",
+ "@planetMagnitude": {
+ "description": "Apparent visual magnitude"
+ },
+ "planetElongation": "距日距角",
+ "@planetElongation": {
+ "description": "Angular distance from the Sun"
+ },
+ "planetSky": "時段",
+ "@planetSky": {
+ "description": "Label for whether the planet is an evening or morning object"
+ },
+ "planetEvening": "昏星",
+ "@planetEvening": {
+ "description": "Sets after the Sun, so visible in the evening"
+ },
+ "planetMorning": "晨星",
+ "@planetMorning": {
+ "description": "Rises before the Sun, so visible before dawn"
+ },
+ "planetDistance": "距離",
+ "@planetDistance": {
+ "description": "Distance from the Earth"
+ },
+ "planetAu": "天文單位",
+ "@planetAu": {
+ "description": "Unit suffix: astronomical units"
+ },
+ "planetAltitude": "仰角",
+ "@planetAltitude": {
+ "description": "Height above the horizon right now"
+ },
+ "planetMercury": "水星",
+ "@planetMercury": {
+ "description": "Planet name"
+ },
+ "planetVenus": "金星",
+ "@planetVenus": {
+ "description": "Planet name"
+ },
+ "planetMars": "火星",
+ "@planetMars": {
+ "description": "Planet name"
+ },
+ "planetJupiter": "木星",
+ "@planetJupiter": {
+ "description": "Planet name"
+ },
+ "planetSaturn": "土星",
+ "@planetSaturn": {
+ "description": "Planet name"
+ },
+ "planetUranus": "天王星",
+ "@planetUranus": {
+ "description": "Planet name"
+ },
+ "planetNeptune": "海王星",
+ "@planetNeptune": {
+ "description": "Planet name"
+ },
+ "solarTermVernalEquinox": "春分",
+ "@solarTermVernalEquinox": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermPureBrightness": "清明",
+ "@solarTermPureBrightness": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermGrainRain": "穀雨",
+ "@solarTermGrainRain": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermStartOfSummer": "立夏",
+ "@solarTermStartOfSummer": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermGrainFull": "小滿",
+ "@solarTermGrainFull": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermGrainInEar": "芒種",
+ "@solarTermGrainInEar": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermSummerSolstice": "夏至",
+ "@solarTermSummerSolstice": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermMinorHeat": "小暑",
+ "@solarTermMinorHeat": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermMajorHeat": "大暑",
+ "@solarTermMajorHeat": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermStartOfAutumn": "立秋",
+ "@solarTermStartOfAutumn": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermEndOfHeat": "處暑",
+ "@solarTermEndOfHeat": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermWhiteDew": "白露",
+ "@solarTermWhiteDew": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermAutumnalEquinox": "秋分",
+ "@solarTermAutumnalEquinox": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermColdDew": "寒露",
+ "@solarTermColdDew": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermFrostDescent": "霜降",
+ "@solarTermFrostDescent": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermStartOfWinter": "立冬",
+ "@solarTermStartOfWinter": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermMinorSnow": "小雪",
+ "@solarTermMinorSnow": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermMajorSnow": "大雪",
+ "@solarTermMajorSnow": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermWinterSolstice": "冬至",
+ "@solarTermWinterSolstice": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermMinorCold": "小寒",
+ "@solarTermMinorCold": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermMajorCold": "大寒",
+ "@solarTermMajorCold": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermStartOfSpring": "立春",
+ "@solarTermStartOfSpring": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermRainWater": "雨水",
+ "@solarTermRainWater": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "solarTermAwakeningOfInsects": "驚蟄",
+ "@solarTermAwakeningOfInsects": {
+ "description": "One of the twenty-four solar terms"
+ },
+ "tonightTitle": "今夜",
+ "@tonightTitle": {
+ "description": "Tonight page title"
+ },
+ "tonightSectionDark": "觀測窗口",
+ "@tonightSectionDark": {
+ "description": "Section header: the observing window"
+ },
+ "tonightAstronomicalNight": "天文夜",
+ "@tonightAstronomicalNight": {
+ "description": "Dusk to dawn with the Sun 18 degrees down"
+ },
+ "tonightNeverDark": "整夜唔全暗",
+ "@tonightNeverDark": {
+ "description": "Shown when the Sun never gets 18 degrees below the horizon"
+ },
+ "tonightDarkWindow": "暗窗",
+ "@tonightDarkWindow": {
+ "description": "The longest stretch with no Sun and no Moon"
+ },
+ "tonightMoonAllNight": "月亮整夜喺天上",
+ "@tonightMoonAllNight": {
+ "description": "Shown when the Moon is up for the whole night"
+ },
+ "tonightDarkTotal": "總暗時",
+ "@tonightDarkTotal": {
+ "description": "Total dark time, hours:minutes"
+ },
+ "tonightMoonlight": "月光",
+ "@tonightMoonlight": {
+ "description": "The Moon's illuminated fraction tonight"
+ },
+ "tonightSectionShowers": "流星雨",
+ "@tonightSectionShowers": {
+ "description": "Section header: meteor showers running now"
+ },
+ "tonightRadiantDown": "輻射點唔升起",
+ "@tonightRadiantDown": {
+ "description": "The shower's radiant never rises here"
+ },
+ "tonightPerHour": "顆/時",
+ "@tonightPerHour": {
+ "description": "Unit: meteors per hour"
+ },
+ "tonightSectionSatellites": "衛星過境",
+ "@tonightSectionSatellites": {
+ "description": "Section header: visible satellite passes"
+ },
+ "tonightSectionTargets": "此刻可觀測目標",
+ "@tonightSectionTargets": {
+ "description": "Section header: deep-sky objects high enough to observe"
+ },
+ "showerQuadrantids": "象限儀座",
+ "@showerQuadrantids": {
+ "description": "Meteor shower name"
+ },
+ "showerLyrids": "天琴座",
+ "@showerLyrids": {
+ "description": "Meteor shower name"
+ },
+ "showerEtaAquariids": "寶瓶座η",
+ "@showerEtaAquariids": {
+ "description": "Meteor shower name"
+ },
+ "showerDeltaAquariids": "寶瓶座δ",
+ "@showerDeltaAquariids": {
+ "description": "Meteor shower name"
+ },
+ "showerPerseids": "英仙座",
+ "@showerPerseids": {
+ "description": "Meteor shower name"
+ },
+ "showerOrionids": "獵戶座",
+ "@showerOrionids": {
+ "description": "Meteor shower name"
+ },
+ "showerSouthernTaurids": "金牛座南",
+ "@showerSouthernTaurids": {
+ "description": "Meteor shower name"
+ },
+ "showerLeonids": "獅子座",
+ "@showerLeonids": {
+ "description": "Meteor shower name"
+ },
+ "showerGeminids": "雙子座",
+ "@showerGeminids": {
+ "description": "Meteor shower name"
+ },
+ "showerUrsids": "小熊座",
+ "@showerUrsids": {
+ "description": "Meteor shower name"
+ },
+ "deepSkyOpenCluster": "疏散星團",
+ "@deepSkyOpenCluster": {
+ "description": "Deep-sky object type"
+ },
+ "deepSkyGlobularCluster": "球狀星團",
+ "@deepSkyGlobularCluster": {
+ "description": "Deep-sky object type"
+ },
+ "deepSkySpiralGalaxy": "螺旋星系",
+ "@deepSkySpiralGalaxy": {
+ "description": "Deep-sky object type"
+ },
+ "deepSkyEllipticalGalaxy": "橢圓星系",
+ "@deepSkyEllipticalGalaxy": {
+ "description": "Deep-sky object type"
+ },
+ "deepSkyIrregularGalaxy": "唔規則星系",
+ "@deepSkyIrregularGalaxy": {
+ "description": "Deep-sky object type"
+ },
+ "deepSkyPlanetaryNebula": "行星狀星雲",
+ "@deepSkyPlanetaryNebula": {
+ "description": "Deep-sky object type"
+ },
+ "deepSkySupernovaRemnant": "超新星遺跡",
+ "@deepSkySupernovaRemnant": {
+ "description": "Deep-sky object type"
+ },
+ "deepSkyEmissionNebula": "發射星雲",
+ "@deepSkyEmissionNebula": {
+ "description": "Deep-sky object type"
+ },
+ "deepSkyReflectionNebula": "反射星雲",
+ "@deepSkyReflectionNebula": {
+ "description": "Deep-sky object type"
+ },
+ "deepSkyAsterism": "星群",
+ "@deepSkyAsterism": {
+ "description": "Deep-sky object type: a star pattern, not a single object"
+ },
+ "almanacTitle": "曆法",
+ "@almanacTitle": {
+ "description": "Almanac page title"
+ },
+ "almanacSectionToday": "今日",
+ "@almanacSectionToday": {
+ "description": "Section header: today's date in both calendars"
+ },
+ "almanacGregorian": "西曆",
+ "@almanacGregorian": {
+ "description": "The Gregorian date"
+ },
+ "almanacLunar": "農曆",
+ "@almanacLunar": {
+ "description": "The lunisolar date"
+ },
+ "almanacYear": "歲次",
+ "@almanacYear": {
+ "description": "The sexagenary year and its zodiac animal"
+ },
+ "almanacMonthLength": "月大小",
+ "@almanacMonthLength": {
+ "description": "Whether this lunar month has 29 or 30 days"
+ },
+ "almanacLongMonth": "三十日",
+ "@almanacLongMonth": {
+ "description": "A 30-day lunar month"
+ },
+ "almanacShortMonth": "二十九日",
+ "@almanacShortMonth": {
+ "description": "A 29-day lunar month"
+ },
+ "almanacLeapPrefix": "閏",
+ "@almanacLeapPrefix": {
+ "description": "Prefix marking an intercalary lunar month"
+ },
+ "almanacSectionLunarEclipses": "月食",
+ "@almanacSectionLunarEclipses": {
+ "description": "Section header: upcoming lunar eclipses"
+ },
+ "almanacSectionSolarEclipses": "日食",
+ "@almanacSectionSolarEclipses": {
+ "description": "Section header: solar eclipses visible from here"
+ },
+ "almanacNoSolarEclipse": "範圍內無",
+ "@almanacNoSolarEclipse": {
+ "description": "No solar eclipse is visible from here in the search window"
+ },
+ "eclipseTotal": "全食",
+ "@eclipseTotal": {
+ "description": "Eclipse type"
+ },
+ "eclipsePartial": "偏食",
+ "@eclipsePartial": {
+ "description": "Eclipse type"
+ },
+ "eclipseAnnular": "環食",
+ "@eclipseAnnular": {
+ "description": "Eclipse type: a ring of Sun remains"
+ },
+ "eclipsePenumbral": "半影食",
+ "@eclipsePenumbral": {
+ "description": "Eclipse type: the Moon only enters the outer shadow"
+ },
+ "zodiacRat": "鼠",
+ "@zodiacRat": {
+ "description": "Chinese zodiac animal"
+ },
+ "zodiacOx": "牛",
+ "@zodiacOx": {
+ "description": "Chinese zodiac animal"
+ },
+ "zodiacTiger": "虎",
+ "@zodiacTiger": {
+ "description": "Chinese zodiac animal"
+ },
+ "zodiacRabbit": "兔",
+ "@zodiacRabbit": {
+ "description": "Chinese zodiac animal"
+ },
+ "zodiacDragon": "龍",
+ "@zodiacDragon": {
+ "description": "Chinese zodiac animal"
+ },
+ "zodiacSnake": "蛇",
+ "@zodiacSnake": {
+ "description": "Chinese zodiac animal"
+ },
+ "zodiacHorse": "馬",
+ "@zodiacHorse": {
+ "description": "Chinese zodiac animal"
+ },
+ "zodiacGoat": "羊",
+ "@zodiacGoat": {
+ "description": "Chinese zodiac animal"
+ },
+ "zodiacMonkey": "猴",
+ "@zodiacMonkey": {
+ "description": "Chinese zodiac animal"
+ },
+ "zodiacRooster": "雞",
+ "@zodiacRooster": {
+ "description": "Chinese zodiac animal"
+ },
+ "zodiacDog": "狗",
+ "@zodiacDog": {
+ "description": "Chinese zodiac animal"
+ },
+ "zodiacPig": "豬",
+ "@zodiacPig": {
+ "description": "Chinese zodiac animal"
+ },
+ "tideTitle": "潮汐",
+ "@tideTitle": {
+ "description": "Tide page title"
+ },
+ "tideDisclaimer": "僅為天文引潮力,非港口潮汐表。水位請參考氣象署公布嘅潮汐預報。",
+ "@tideDisclaimer": {
+ "description": "Says plainly that this is the astronomical forcing, not a harbour tide table"
+ },
+ "tideSectionNow": "此刻",
+ "@tideSectionNow": {
+ "description": "Section header: the tide-raising force right now"
+ },
+ "tidePhase": "週期",
+ "@tidePhase": {
+ "description": "Where in the spring-neap cycle the tide sits"
+ },
+ "tideSpring": "大潮",
+ "@tideSpring": {
+ "description": "Spring tide: Sun and Moon aligned"
+ },
+ "tideNeap": "小潮",
+ "@tideNeap": {
+ "description": "Neap tide: Sun and Moon at right angles"
+ },
+ "tideMiddling": "中潮",
+ "@tideMiddling": {
+ "description": "Between spring and neap"
+ },
+ "tideLunarDistanceFactor": "月球引力",
+ "@tideLunarDistanceFactor": {
+ "description": "How much stronger the Moon's pull is than at mean distance"
+ },
+ "tideEquilibrium": "平衡潮高",
+ "@tideEquilibrium": {
+ "description": "The equilibrium tide height"
+ },
+ "tideMetres": "公尺",
+ "@tideMetres": {
+ "description": "Unit: metres"
+ },
+ "tidePerigeanSpring": "下次近地點大潮",
+ "@tidePerigeanSpring": {
+ "description": "The next spring tide at lunar perigee - the highest water"
+ },
+ "tideSectionTurningPoints": "轉折點",
+ "@tideSectionTurningPoints": {
+ "description": "Section header: when the forcing peaks and troughs"
+ },
+ "tideHigh": "高",
+ "@tideHigh": {
+ "description": "A high point of the tidal forcing"
+ },
+ "tideLow": "低",
+ "@tideLow": {
+ "description": "A low point of the tidal forcing"
+ },
+ "skyChartTitle": "星圖",
+ "@skyChartTitle": {
+ "description": "Sky chart page title"
+ },
+ "skyChartNorth": "北",
+ "@skyChartNorth": {
+ "description": "Compass point on the sky chart"
+ },
+ "skyChartEast": "東",
+ "@skyChartEast": {
+ "description": "Compass point on the sky chart"
+ },
+ "skyChartSouth": "南",
+ "@skyChartSouth": {
+ "description": "Compass point on the sky chart"
+ },
+ "skyChartWest": "西",
+ "@skyChartWest": {
+ "description": "Compass point on the sky chart"
+ },
+ "tonightElementAge": "軌道資料 {days} 天前",
+ "@tonightElementAge": {
+ "description": "How old the bundled satellite element set is, in days",
+ "placeholders": {
+ "days": {
+ "type": "int"
+ }
+ }
+ },
+ "almanacLunarDate": "{leap}{month} 月 {day} 日",
+ "@almanacLunarDate": {
+ "description": "A lunisolar date: an optional leap marker, the month and the day",
+ "placeholders": {
+ "leap": {
+ "type": "String"
+ },
+ "month": {
+ "type": "int"
+ },
+ "day": {
+ "type": "int"
+ }
+ }
+ },
+ "tonightNoShowers": "而家無流星雨",
+ "@tonightNoShowers": {
+ "description": "Shown when no meteor shower is running today"
+ },
+ "tonightNoPasses": "48 小時內無可見過境",
+ "@tonightNoPasses": {
+ "description": "Shown when no satellite pass is visible in the next two days"
+ },
+ "tonightSatellitesUnavailable": "冇辦法讀取軌道資料",
+ "@tonightSatellitesUnavailable": {
+ "description": "Shown when the bundled element set could not be read"
+ },
+ "tonightNoTargets": "無足夠高度嘅目標",
+ "@tonightNoTargets": {
+ "description": "Shown when nothing in the catalogue is high enough tonight"
+ },
+ "skyChartUnavailable": "冇辦法讀取星表",
+ "@skyChartUnavailable": {
+ "description": "Shown when the bundled star catalogue could not be read"
+ },
+ "permissionSettingsTitle": "請到系統設定開啟",
+ "@permissionSettingsTitle": {
+ "description": "Dialog title: the permission must be granted in system settings"
+ },
+ "permissionSettingsHint": "返回 App 後會自動重新檢查。",
+ "@permissionSettingsHint": {
+ "description": "Reassures the user they can come back and that the app re-checks on return"
+ },
+ "permissionOpenSettings": "前往設定",
+ "@permissionOpenSettings": {
+ "description": "Button that opens the system settings page"
+ },
+ "permissionSettingsMessage": "「{what}」已被拒絕,系統唔會再詢問。請到設定中開啟。",
+ "permissionGuideNotification": "請到系統設定中開啟通知權限。",
+ "permissionGuideForegroundLocation": "請到系統設定中開啟精確位置權限。",
+ "permissionGuideBackgroundLocation": "請喺「{option}」中改為「允許所有時間」。",
+ "@permissionGuideBackgroundLocation": {
+ "description": "Instruction for background location",
+ "placeholders": {
+ "option": {}
+ }
+ },
+ "permissionGuideBackgroundExecution": "請到系統設定中允許背景執行,避免收到通知時被系統暫停。",
+ "permissionGuideUnusedPause": "若應用程式被標記為「未使用」,請喺系統設定中改為「允許」。",
+ "permissionGuideUnusedFreeSpace": "若應用程式因暫存空間唔夠被暫停,請清除暫存後重新開啟。",
+ "permissionGuideUnusedRevoke": "若應用程式權限被撤銷,請喺系統設定中重新授予。",
+ "permissionGuideUnusedPlayProtect": "若被 Play 保護機制暫停,請到 Google Play 中檢查應用程式狀態。",
+ "permissionGuideVendorPower": "請到「{vendor}」嘅省電設定中,將本應用程式設為「唔限制」。",
+ "@permissionGuideVendorPower": {
+ "description": "Instruction for vendor power saving",
+ "placeholders": {
+ "vendor": {}
+ }
+ },
+ "permissionStillRequired": "仍然需要此權限,請到設定中開啟。",
+ "permissionVerifyManually": "請手動確認此權限已喺系統設定中開啟。",
+ "permissionBackgroundLocationOption": "「允許所有時間」",
+ "@permissionSettingsMessage": {
+ "description": "Explains that the system will not ask again for this permission",
+ "placeholders": {
+ "what": {
+ "type": "String"
+ }
+ }
+ },
+ "displayTextSize": "文字大小",
+ "displayTextSizeDesc": "只調整 App 介面嘅文字,地圖上嘅文字維持原本大小。",
+ "displayTextWeight": "文字粗細",
+ "displayTextWeightDesc": "文字較粗時可能更容易閱讀。",
+ "displayContrast": "對比度",
+ "displayContrastDesc": "對比越高,文字同背景越分明。",
+ "displayColorVision": "色覺調整",
+ "displayColorVisionDesc": "整個 App 嘅顏色都會一併調整,包括地圖。",
+ "displayColorVisionNone": "標準",
+ "displayColorVisionProtan": "紅色弱",
+ "displayColorVisionDeutan": "綠色弱",
+ "displayColorVisionTritan": "藍黃色弱",
+ "displayPreviewSample": "地震報告範例",
+ "displayScaleSmall": "小",
+ "displayScaleDefault": "預設",
+ "displayScaleLarge": "大",
+ "displayScaleHuge": "特大",
+ "displayWeightNormal": "一般",
+ "displayWeightMedium": "中等",
+ "displayWeightBold": "粗體",
+ "displayContrastStandard": "標準",
+ "displayContrastMedium": "中等",
+ "displayContrastHigh": "高",
+ "meshtasticDirect": "直連",
+ "meshtasticHopsAway": "{n} 跳",
+ "meshtasticStatRelayShare": "為他人轉發",
+ "meshtasticStatRelayShareHint": "佔本機發送量嘅比例",
+ "meshtasticStatRelayValue": "轉發成功率",
+ "meshtasticStatRelaySolePath": "經常係唯一路徑 — 網絡依賴此節點",
+ "meshtasticStatRelayRedundant": "其他節點都覆蓋同樣路徑",
+ "meshtasticStatRedundancy": "重複接收",
+ "meshtasticStatThinEdge": "備援路徑少 — 一個中繼失效就可能斷線",
+ "meshtasticStatWellCovered": "有多條路徑可達",
+ "meshtasticStatErrorRate": "接收錯誤率",
+ "meshtasticStatErrorRateHint": "空中時間唔變卻升高 = 干擾",
+ "meshtasticTraceRoute": "追蹤路由",
+ "@meshtasticTraceRoute": {
+ "description": "Sheet action: ask the mesh how this node is reached"
+ },
+ "meshtasticTracing": "追蹤中…",
+ "@meshtasticTracing": {
+ "description": "Sheet button while a traceroute probe is in flight"
+ },
+ "meshtasticTraceUnreadable": "冇辦法解讀嘅回覆",
+ "meshtasticTraceOffline": "未連線至電台",
+ "meshtasticTraceCooldown": "電台限制每 30 秒一次",
+ "meshtasticTraceNoReply": "冇回應 — 超出範圍或金鑰唔同",
+ "@meshtasticTraceNoReply": {
+ "description": "Traceroute outcome when the destination never answers"
+ },
+ "meshtasticTraceDirect": "直達 — 中間無中繼",
+ "@meshtasticTraceDirect": {
+ "description": "Traceroute outcome for a one-hop route"
+ },
+ "meshtasticTraceHops": "{n} 跳",
+ "@meshtasticTraceHops": {
+ "description": "Traceroute outcome hop count",
+ "placeholders": {
+ "n": {
+ "type": "int"
+ }
+ }
+ },
+ "moreDumpDiagnostics": "傾印除錯資訊及日誌",
+ "moreDumpDiagnosticsHint": "上載後複製連結",
+ "dumpIncludeSensitive": "包含精確位置",
+ "dumpIncludeSensitiveHint": "包含日誌同背景定位入面嘅座標;唔勾選就會以 null 取代",
+ "dumpUpload": "上載",
+ "dumpUploaded": "已上載",
+ "dumpLinkCopied": "連結已複製到剪貼簿",
+ "dumpCopyAgain": "再複製一次",
+ "dumpUploadFailed": "上載失敗,請稍後再試",
+ "statusLegendUnprobed": "未探測",
+ "statusLegendUnsupported": "唔支援"
+}
diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb
index 452eed9c8..b2ec96a06 100644
--- a/lib/l10n/app_zh.arb
+++ b/lib/l10n/app_zh.arb
@@ -1007,9 +1007,10 @@
"moreAnnouncements": "公告",
"moreTagline": "防災資訊整合平台",
"moreVersionStable": "正式版",
- "moreVersionNotes": "目前版本",
+ "moreVersionNotes": "本次更新",
+ "moreVersionNotesHighlightsSubtitle": "這個版本做了哪些改變",
"releaseHighlightsSeeNotes": "查看完整更新日誌",
- "releaseHighlightsTitle": "本次更新",
+ "releaseHighlightsTitle": "{train} 重點整理",
"releaseHighlightsTabNormal": "做了哪些改變",
"releaseHighlightsTabAdvanced": "深入技術",
"releaseHighlightsEmpty": "目前沒有內容。",
@@ -1091,20 +1092,57 @@
"meshtasticRegionConfirm": "要將這台裝置切換為 TW 地區嗎?裝置會重新啟動並短暫斷線,上面的其他頻道也會一起改變。",
"dataEarthquakeSubtitle": "地震報告",
"typhoonNoActive": "目前無颱風",
- "@meshtasticExcludeMqttHidden": {
- "description": "How many nodes the filter is hiding",
- "placeholders": {
- "count": {
- "type": "int"
- }
- }
- },
"mapLayerSatelliteB11": "ひまわり 二氧化硫/雲相(B11)",
"navEvents": "事件",
"onboardingTermsTitle": "服務條款",
"@meshtasticChannels": {
"description": "Section: the radio's channel table"
},
+ "mapOsmOverlay": "詳細地圖",
+ "mapOsmOverlayHint": "顯示更完整的道路、建物與地名",
+ "mapOsmDetails": "詳細設定",
+ "moreDataSources": "資料來源",
+ "dataSourceTremNet": "探索智慧科技有限公司 — TREM-Net",
+ "dataSourceCwa": "交通部中央氣象署 (CWA)",
+ "dataSourceJma": "気象庁 (JMA)",
+ "dataSourceNcdr": "國家災害防救科技中心 (NCDR)",
+ "dataSourceEcmwf": "European Centre for Medium-Range Weather Forecasts (ECMWF)",
+ "dataSourceNoaaGfs": "National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)",
+ "dataSourceGovernmentOpenData": "政府資料開放平臺",
+ "dataSourceOpenStreetMap": "© OpenStreetMap contributors",
+ "dataSourceNasaMoon": "National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)",
+ "mapOsmDetailsHint": "已啟用 {enabled} / 共 {total} 個圖層",
+ "@mapOsmDetailsHint": {
+ "description": "How many of the OSM layers are enabled",
+ "placeholders": {
+ "enabled": {
+ "type": "int"
+ },
+ "total": {
+ "type": "int"
+ }
+ }
+ },
+ "mapOsmSurface": "地表",
+ "mapOsmParks": "公園",
+ "mapOsmLandUse": "土地利用",
+ "mapOsmAirportAreas": "機場區域",
+ "mapOsmWater": "水域",
+ "mapOsmRivers": "河川",
+ "mapOsmBoundaries": "邊界",
+ "mapOsmBuildings": "建物",
+ "mapOsmRoads": "道路",
+ "mapOsmRoadNames": "道路名稱",
+ "mapOsmWaterNames": "水域名稱",
+ "mapOsmPeaks": "山峰",
+ "mapOsmAirportNames": "機場名稱",
+ "mapOsmPlaceNames": "地名",
+ "mapOsmPoi": "地標",
+ "mapOsmHouseNumbers": "門牌號碼",
+ "mapOsmRestoreAll": "全部恢復",
+ "mapOsmSectionNatural": "地表與自然",
+ "mapOsmSectionRoadsAndBuildings": "道路與建物",
+ "mapOsmSectionLabelsAndPlaces": "地名與標示",
"mapTownLabels": "鄉鎮名稱",
"notifySetFailed": "設定失敗,請稍後再試。",
"meshtasticDisconnect": "斷線",
@@ -1799,6 +1837,30 @@
"description": "Button that opens the system settings page"
},
"permissionSettingsMessage": "「{what}」已被拒絕,系統不會再詢問。請到設定中開啟。",
+ "permissionGuideNotification": "請到系統設定中開啟通知權限。",
+ "permissionGuideForegroundLocation": "請到系統設定中開啟精確位置權限。",
+ "permissionGuideBackgroundLocation": "請在「{option}」中改為「允許所有時間」。",
+ "@permissionGuideBackgroundLocation": {
+ "description": "Instruction for background location",
+ "placeholders": {
+ "option": {}
+ }
+ },
+ "permissionGuideBackgroundExecution": "請到系統設定中允許背景執行,避免收到通知時被系統暫停。",
+ "permissionGuideUnusedPause": "若應用程式被標記為「未使用」,請在系統設定中改為「允許」。",
+ "permissionGuideUnusedFreeSpace": "若應用程式因暫存空間不足被暫停,請清除暫存後重新開啟。",
+ "permissionGuideUnusedRevoke": "若應用程式權限被撤銷,請在系統設定中重新授予。",
+ "permissionGuideUnusedPlayProtect": "若被 Play 保護機制暫停,請到 Google Play 中檢查應用程式狀態。",
+ "permissionGuideVendorPower": "請到「{vendor}」的省電設定中,將本應用程式設為「不限制」。",
+ "@permissionGuideVendorPower": {
+ "description": "Instruction for vendor power saving",
+ "placeholders": {
+ "vendor": {}
+ }
+ },
+ "permissionStillRequired": "仍然需要此權限,請到設定中開啟。",
+ "permissionVerifyManually": "請手動確認此權限已在系統設定中開啟。",
+ "permissionBackgroundLocationOption": "「允許所有時間」",
"@permissionSettingsMessage": {
"description": "Explains that the system will not ask again for this permission",
"placeholders": {
@@ -1872,6 +1934,9 @@
},
"moreDumpDiagnostics": "傾印除錯資訊及日誌",
"moreDumpDiagnosticsHint": "上傳後複製連結",
+ "dumpIncludeSensitive": "包含精確位置",
+ "dumpIncludeSensitiveHint": "包含日誌與背景定位中的座標;未勾選時會以 null 取代",
+ "dumpUpload": "上傳",
"dumpUploaded": "已上傳",
"dumpLinkCopied": "連結已複製到剪貼簿",
"dumpCopyAgain": "再複製一次",
diff --git a/lib/l10n/app_zh_Hans.arb b/lib/l10n/app_zh_Hans.arb
index c428eb61b..3c5c51073 100644
--- a/lib/l10n/app_zh_Hans.arb
+++ b/lib/l10n/app_zh_Hans.arb
@@ -1007,9 +1007,10 @@
"moreAnnouncements": "公告",
"moreTagline": "防灾信息整合平台",
"moreVersionStable": "正式版",
- "moreVersionNotes": "当前版本",
+ "moreVersionNotes": "本次更新",
+ "moreVersionNotesHighlightsSubtitle": "这个版本做了哪些改变",
"releaseHighlightsSeeNotes": "查看完整更新日志",
- "releaseHighlightsTitle": "本次更新",
+ "releaseHighlightsTitle": "{train} 重点整理",
"releaseHighlightsTabNormal": "做了哪些改变",
"releaseHighlightsTabAdvanced": "深入技术",
"releaseHighlightsEmpty": "目前没有内容。",
@@ -1105,6 +1106,51 @@
"@meshtasticChannels": {
"description": "Section: the radio's channel table"
},
+ "mapOsmOverlay": "详细地图",
+ "mapOsmOverlayHint": "显示更完整的道路、建筑和地名",
+ "mapOsmDetails": "详细设置",
+ "moreDataSources": "数据来源",
+ "dataSourceTremNet": "探索智慧科技有限公司 — TREM-Net",
+ "dataSourceCwa": "交通部中央氣象署 (CWA)",
+ "dataSourceJma": "気象庁 (JMA)",
+ "dataSourceNcdr": "國家災害防救科技中心 (NCDR)",
+ "dataSourceEcmwf": "European Centre for Medium-Range Weather Forecasts (ECMWF)",
+ "dataSourceNoaaGfs": "National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)",
+ "dataSourceGovernmentOpenData": "政府資料開放平臺",
+ "dataSourceOpenStreetMap": "© OpenStreetMap contributors",
+ "dataSourceNasaMoon": "National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)",
+ "mapOsmDetailsHint": "已启用 {enabled} / 共 {total} 个图层",
+ "@mapOsmDetailsHint": {
+ "description": "How many of the OSM layers are enabled",
+ "placeholders": {
+ "enabled": {
+ "type": "int"
+ },
+ "total": {
+ "type": "int"
+ }
+ }
+ },
+ "mapOsmSurface": "地表",
+ "mapOsmParks": "公园",
+ "mapOsmLandUse": "土地利用",
+ "mapOsmAirportAreas": "机场区域",
+ "mapOsmWater": "水域",
+ "mapOsmRivers": "河川",
+ "mapOsmBoundaries": "边界",
+ "mapOsmBuildings": "建筑物",
+ "mapOsmRoads": "道路",
+ "mapOsmRoadNames": "道路名称",
+ "mapOsmWaterNames": "水域名称",
+ "mapOsmPeaks": "山峰",
+ "mapOsmAirportNames": "机场名称",
+ "mapOsmPlaceNames": "地名",
+ "mapOsmPoi": "地标",
+ "mapOsmHouseNumbers": "门牌号码",
+ "mapOsmRestoreAll": "全部恢复",
+ "mapOsmSectionNatural": "地表与自然",
+ "mapOsmSectionRoadsAndBuildings": "道路与建筑",
+ "mapOsmSectionLabelsAndPlaces": "地名与标注",
"mapTownLabels": "乡镇名称",
"notifySetFailed": "设置失败,请稍后再试。",
"meshtasticDisconnect": "斷線",
@@ -1799,6 +1845,30 @@
"description": "Button that opens the system settings page"
},
"permissionSettingsMessage": "「{what}」已被拒绝,系统不会再询问。请到设置中开启。",
+ "permissionGuideNotification": "请到系统设置中开启通知权限。",
+ "permissionGuideForegroundLocation": "请到系统设置中开启精确位置权限。",
+ "permissionGuideBackgroundLocation": "请在「{option}」中改为「允许所有时间」。",
+ "@permissionGuideBackgroundLocation": {
+ "description": "Instruction for background location",
+ "placeholders": {
+ "option": {}
+ }
+ },
+ "permissionGuideBackgroundExecution": "请到系统设置中允许后台执行,避免收到通知时被系统暂停。",
+ "permissionGuideUnusedPause": "若应用被标记为「未使用」,请在系统设置中改为「允许」。",
+ "permissionGuideUnusedFreeSpace": "若应用因缓存空间不足被暂停,请清除缓存后重新打开。",
+ "permissionGuideUnusedRevoke": "若应用权限被撤销,请在系统设置中重新授予。",
+ "permissionGuideUnusedPlayProtect": "若被 Play 保护机制暂停,请到 Google Play 中检查应用状态。",
+ "permissionGuideVendorPower": "请到「{vendor}」的省电设置中,将本应用设为「不限制」。",
+ "@permissionGuideVendorPower": {
+ "description": "Instruction for vendor power saving",
+ "placeholders": {
+ "vendor": {}
+ }
+ },
+ "permissionStillRequired": "仍然需要此权限,请到设置中打开。",
+ "permissionVerifyManually": "请手动确认此权限已在系统设置中打开。",
+ "permissionBackgroundLocationOption": "「允许所有时间」",
"@permissionSettingsMessage": {
"description": "Explains that the system will not ask again for this permission",
"placeholders": {
@@ -1872,6 +1942,9 @@
},
"moreDumpDiagnostics": "转储调试信息及日志",
"moreDumpDiagnosticsHint": "上传后复制链接,附在反馈里就不用贴一整页",
+ "dumpIncludeSensitive": "包含精确位置",
+ "dumpIncludeSensitiveHint": "包含日志和后台定位中的坐标;未勾选时将以 null 替代",
+ "dumpUpload": "上传",
"dumpUploaded": "已上传",
"dumpLinkCopied": "链接已复制到剪贴板",
"dumpCopyAgain": "再复制一次",
diff --git a/lib/l10n/app_zh_Hant_HK.arb b/lib/l10n/app_zh_Hant_HK.arb
index 14f912ee4..3fe7caf2d 100644
--- a/lib/l10n/app_zh_Hant_HK.arb
+++ b/lib/l10n/app_zh_Hant_HK.arb
@@ -1007,9 +1007,10 @@
"moreAnnouncements": "公告",
"moreTagline": "防災資訊整合平台",
"moreVersionStable": "正式版",
- "moreVersionNotes": "目前版本",
+ "moreVersionNotes": "本次更新",
+ "moreVersionNotesHighlightsSubtitle": "這個版本做了哪些改變",
"releaseHighlightsSeeNotes": "查看完整更新日誌",
- "releaseHighlightsTitle": "本次更新",
+ "releaseHighlightsTitle": "{train} 重點整理",
"releaseHighlightsTabNormal": "做了哪些改變",
"releaseHighlightsTabAdvanced": "深入技術",
"releaseHighlightsEmpty": "目前沒有內容。",
@@ -1105,6 +1106,51 @@
"@meshtasticChannels": {
"description": "Section: the radio's channel table"
},
+ "mapOsmOverlay": "詳細地圖",
+ "mapOsmOverlayHint": "顯示更完整的道路、建物與地名",
+ "mapOsmDetails": "詳細設定",
+ "moreDataSources": "資料來源",
+ "dataSourceTremNet": "探索智慧科技有限公司 — TREM-Net",
+ "dataSourceCwa": "交通部中央氣象署 (CWA)",
+ "dataSourceJma": "気象庁 (JMA)",
+ "dataSourceNcdr": "國家災害防救科技中心 (NCDR)",
+ "dataSourceEcmwf": "European Centre for Medium-Range Weather Forecasts (ECMWF)",
+ "dataSourceNoaaGfs": "National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)",
+ "dataSourceGovernmentOpenData": "政府資料開放平臺",
+ "dataSourceOpenStreetMap": "© OpenStreetMap contributors",
+ "dataSourceNasaMoon": "National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)",
+ "mapOsmDetailsHint": "已啟用 {enabled} / 共 {total} 個圖層",
+ "@mapOsmDetailsHint": {
+ "description": "How many of the OSM layers are enabled",
+ "placeholders": {
+ "enabled": {
+ "type": "int"
+ },
+ "total": {
+ "type": "int"
+ }
+ }
+ },
+ "mapOsmSurface": "地表",
+ "mapOsmParks": "公園",
+ "mapOsmLandUse": "土地利用",
+ "mapOsmAirportAreas": "機場區域",
+ "mapOsmWater": "水域",
+ "mapOsmRivers": "河川",
+ "mapOsmBoundaries": "邊界",
+ "mapOsmBuildings": "建物",
+ "mapOsmRoads": "道路",
+ "mapOsmRoadNames": "道路名稱",
+ "mapOsmWaterNames": "水域名稱",
+ "mapOsmPeaks": "山峰",
+ "mapOsmAirportNames": "機場名稱",
+ "mapOsmPlaceNames": "地名",
+ "mapOsmPoi": "地標",
+ "mapOsmHouseNumbers": "門牌號碼",
+ "mapOsmRestoreAll": "全部恢復",
+ "mapOsmSectionNatural": "地表與自然",
+ "mapOsmSectionRoadsAndBuildings": "道路與建物",
+ "mapOsmSectionLabelsAndPlaces": "地名與標示",
"mapTownLabels": "鄉鎮名稱",
"notifySetFailed": "設定失敗,請稍後再試。",
"meshtasticDisconnect": "斷線",
@@ -1799,6 +1845,30 @@
"description": "Button that opens the system settings page"
},
"permissionSettingsMessage": "「{what}」已被拒絕,系統不會再詢問。請到設定中開啟。",
+ "permissionGuideNotification": "請到系統設定中開啟通知權限。",
+ "permissionGuideForegroundLocation": "請到系統設定中開啟精確位置權限。",
+ "permissionGuideBackgroundLocation": "請在「{option}」中改為「允許所有時間」。",
+ "@permissionGuideBackgroundLocation": {
+ "description": "Instruction for background location",
+ "placeholders": {
+ "option": {}
+ }
+ },
+ "permissionGuideBackgroundExecution": "請到系統設定中允許背景執行,避免收到通知時被系統暫停。",
+ "permissionGuideUnusedPause": "若應用程式被標記為「未使用」,請在系統設定中改為「允許」。",
+ "permissionGuideUnusedFreeSpace": "若應用程式因暫存空間不足被暫停,請清除暫存後重新開啟。",
+ "permissionGuideUnusedRevoke": "若應用程式權限被撤銷,請在系統設定中重新授予。",
+ "permissionGuideUnusedPlayProtect": "若被 Play 保護機制暫停,請到 Google Play 中檢查應用程式狀態。",
+ "permissionGuideVendorPower": "請到「{vendor}」的省電設定中,將本應用程式設為「不限制」。",
+ "@permissionGuideVendorPower": {
+ "description": "Instruction for vendor power saving",
+ "placeholders": {
+ "vendor": {}
+ }
+ },
+ "permissionStillRequired": "仍然需要此權限,請到設定中開啟。",
+ "permissionVerifyManually": "請手動確認此權限已在系統設定中開啟。",
+ "permissionBackgroundLocationOption": "「允許所有時間」",
"@permissionSettingsMessage": {
"description": "Explains that the system will not ask again for this permission",
"placeholders": {
@@ -1872,6 +1942,9 @@
},
"moreDumpDiagnostics": "傾印除錯資訊及日誌",
"moreDumpDiagnosticsHint": "上載後複製連結",
+ "dumpIncludeSensitive": "包含精確位置",
+ "dumpIncludeSensitiveHint": "包含日誌及背景定位中的座標;未勾選時會以 null 取代",
+ "dumpUpload": "上載",
"dumpUploaded": "已上載",
"dumpLinkCopied": "連結已複製到剪貼簿",
"dumpCopyAgain": "再複製一次",
diff --git a/lib/l10n/app_zh_TW.arb b/lib/l10n/app_zh_TW.arb
index cfa2974d7..6572933c2 100644
--- a/lib/l10n/app_zh_TW.arb
+++ b/lib/l10n/app_zh_TW.arb
@@ -1007,9 +1007,10 @@
"moreAnnouncements": "公告",
"moreTagline": "防災資訊整合平台",
"moreVersionStable": "正式版",
- "moreVersionNotes": "目前版本",
+ "moreVersionNotes": "本次更新",
+ "moreVersionNotesHighlightsSubtitle": "這個版本做了哪些改變",
"releaseHighlightsSeeNotes": "查看完整更新日誌",
- "releaseHighlightsTitle": "本次更新",
+ "releaseHighlightsTitle": "{train} 重點整理",
"releaseHighlightsTabNormal": "做了哪些改變",
"releaseHighlightsTabAdvanced": "深入技術",
"releaseHighlightsEmpty": "目前沒有內容。",
@@ -1105,6 +1106,51 @@
"@meshtasticChannels": {
"description": "Section: the radio's channel table"
},
+ "mapOsmOverlay": "詳細地圖",
+ "mapOsmOverlayHint": "顯示更完整的道路、建物與地名",
+ "mapOsmDetails": "詳細設定",
+ "moreDataSources": "資料來源",
+ "dataSourceTremNet": "探索智慧科技有限公司 — TREM-Net",
+ "dataSourceCwa": "交通部中央氣象署 (CWA)",
+ "dataSourceJma": "気象庁 (JMA)",
+ "dataSourceNcdr": "國家災害防救科技中心 (NCDR)",
+ "dataSourceEcmwf": "European Centre for Medium-Range Weather Forecasts (ECMWF)",
+ "dataSourceNoaaGfs": "National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)",
+ "dataSourceGovernmentOpenData": "政府資料開放平臺",
+ "dataSourceOpenStreetMap": "© OpenStreetMap contributors",
+ "dataSourceNasaMoon": "National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)",
+ "mapOsmDetailsHint": "已啟用 {enabled} / 共 {total} 個圖層",
+ "@mapOsmDetailsHint": {
+ "description": "How many of the OSM layers are enabled",
+ "placeholders": {
+ "enabled": {
+ "type": "int"
+ },
+ "total": {
+ "type": "int"
+ }
+ }
+ },
+ "mapOsmSurface": "地表",
+ "mapOsmParks": "公園",
+ "mapOsmLandUse": "土地利用",
+ "mapOsmAirportAreas": "機場區域",
+ "mapOsmWater": "水域",
+ "mapOsmRivers": "河川",
+ "mapOsmBoundaries": "邊界",
+ "mapOsmBuildings": "建物",
+ "mapOsmRoads": "道路",
+ "mapOsmRoadNames": "道路名稱",
+ "mapOsmWaterNames": "水域名稱",
+ "mapOsmPeaks": "山峰",
+ "mapOsmAirportNames": "機場名稱",
+ "mapOsmPlaceNames": "地名",
+ "mapOsmPoi": "地標",
+ "mapOsmHouseNumbers": "門牌號碼",
+ "mapOsmRestoreAll": "全部恢復",
+ "mapOsmSectionNatural": "地表與自然",
+ "mapOsmSectionRoadsAndBuildings": "道路與建物",
+ "mapOsmSectionLabelsAndPlaces": "地名與標示",
"mapTownLabels": "鄉鎮名稱",
"notifySetFailed": "設定失敗,請稍後再試。",
"meshtasticDisconnect": "斷線",
@@ -1799,6 +1845,30 @@
"description": "Button that opens the system settings page"
},
"permissionSettingsMessage": "「{what}」已被拒絕,系統不會再詢問。請到設定中開啟。",
+ "permissionGuideNotification": "請到系統設定中開啟通知權限。",
+ "permissionGuideForegroundLocation": "請到系統設定中開啟精確位置權限。",
+ "permissionGuideBackgroundLocation": "請在「{option}」中改為「允許所有時間」。",
+ "@permissionGuideBackgroundLocation": {
+ "description": "Instruction for background location",
+ "placeholders": {
+ "option": {}
+ }
+ },
+ "permissionGuideBackgroundExecution": "請到系統設定中允許背景執行,避免收到通知時被系統暫停。",
+ "permissionGuideUnusedPause": "若應用程式被標記為「未使用」,請在系統設定中改為「允許」。",
+ "permissionGuideUnusedFreeSpace": "若應用程式因暫存空間不足被暫停,請清除暫存後重新開啟。",
+ "permissionGuideUnusedRevoke": "若應用程式權限被撤銷,請在系統設定中重新授予。",
+ "permissionGuideUnusedPlayProtect": "若被 Play 保護機制暫停,請到 Google Play 中檢查應用程式狀態。",
+ "permissionGuideVendorPower": "請到「{vendor}」的省電設定中,將本應用程式設為「不限制」。",
+ "@permissionGuideVendorPower": {
+ "description": "Instruction for vendor power saving",
+ "placeholders": {
+ "vendor": {}
+ }
+ },
+ "permissionStillRequired": "仍然需要此權限,請到設定中開啟。",
+ "permissionVerifyManually": "請手動確認此權限已在系統設定中開啟。",
+ "permissionBackgroundLocationOption": "「允許所有時間」",
"@permissionSettingsMessage": {
"description": "Explains that the system will not ask again for this permission",
"placeholders": {
@@ -1872,6 +1942,9 @@
},
"moreDumpDiagnostics": "傾印除錯資訊及日誌",
"moreDumpDiagnosticsHint": "上傳後複製連結",
+ "dumpIncludeSensitive": "包含精確位置",
+ "dumpIncludeSensitiveHint": "包含日誌與背景定位中的座標;未勾選時會以 null 取代",
+ "dumpUpload": "上傳",
"dumpUploaded": "已上傳",
"dumpLinkCopied": "連結已複製到剪貼簿",
"dumpCopyAgain": "再複製一次",
diff --git a/lib/l10n/gen/app_localizations.dart b/lib/l10n/gen/app_localizations.dart
index a0ff3c6df..dcad028fd 100644
--- a/lib/l10n/gen/app_localizations.dart
+++ b/lib/l10n/gen/app_localizations.dart
@@ -12,6 +12,7 @@ import 'app_localizations_ja.dart';
import 'app_localizations_ko.dart';
import 'app_localizations_th.dart';
import 'app_localizations_vi.dart';
+import 'app_localizations_yue.dart';
import 'app_localizations_zh.dart';
// ignore_for_file: type=lint
@@ -107,6 +108,7 @@ abstract class AppLocalizations {
Locale('ko'),
Locale('th'),
Locale('vi'),
+ Locale('yue'),
Locale('zh'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans'),
Locale.fromSubtags(
@@ -4056,14 +4058,20 @@ abstract class AppLocalizations {
/// No description provided for @moreVersionNotes.
///
/// In en, this message translates to:
- /// **'This version'**
+ /// **'This update'**
String get moreVersionNotes;
- /// No description provided for @releaseHighlightsTitle.
+ /// No description provided for @moreVersionNotesHighlightsSubtitle.
///
/// In en, this message translates to:
/// **'What changed in this release'**
- String get releaseHighlightsTitle;
+ String get moreVersionNotesHighlightsSubtitle;
+
+ /// No description provided for @releaseHighlightsTitle.
+ ///
+ /// In en, this message translates to:
+ /// **'{train} key highlights'**
+ String releaseHighlightsTitle(Object train);
/// No description provided for @releaseHighlightsTabNormal.
///
@@ -4395,6 +4403,210 @@ abstract class AppLocalizations {
/// **'Terms of Service'**
String get onboardingTermsTitle;
+ /// No description provided for @mapOsmOverlay.
+ ///
+ /// In en, this message translates to:
+ /// **'Detailed map'**
+ String get mapOsmOverlay;
+
+ /// No description provided for @mapOsmOverlayHint.
+ ///
+ /// In en, this message translates to:
+ /// **'Show more complete roads, buildings, and place labels'**
+ String get mapOsmOverlayHint;
+
+ /// No description provided for @mapOsmDetails.
+ ///
+ /// In en, this message translates to:
+ /// **'Detailed map layers'**
+ String get mapOsmDetails;
+
+ /// Heading above the subtle source-attribution list at the bottom of About
+ ///
+ /// In en, this message translates to:
+ /// **'Data sources'**
+ String get moreDataSources;
+
+ /// No description provided for @dataSourceTremNet.
+ ///
+ /// In en, this message translates to:
+ /// **'探索智慧科技有限公司 — TREM-Net'**
+ String get dataSourceTremNet;
+
+ /// No description provided for @dataSourceCwa.
+ ///
+ /// In en, this message translates to:
+ /// **'交通部中央氣象署 (CWA)'**
+ String get dataSourceCwa;
+
+ /// No description provided for @dataSourceJma.
+ ///
+ /// In en, this message translates to:
+ /// **'気象庁 (JMA)'**
+ String get dataSourceJma;
+
+ /// No description provided for @dataSourceNcdr.
+ ///
+ /// In en, this message translates to:
+ /// **'國家災害防救科技中心 (NCDR)'**
+ String get dataSourceNcdr;
+
+ /// No description provided for @dataSourceEcmwf.
+ ///
+ /// In en, this message translates to:
+ /// **'European Centre for Medium-Range Weather Forecasts (ECMWF)'**
+ String get dataSourceEcmwf;
+
+ /// No description provided for @dataSourceNoaaGfs.
+ ///
+ /// In en, this message translates to:
+ /// **'National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)'**
+ String get dataSourceNoaaGfs;
+
+ /// No description provided for @dataSourceGovernmentOpenData.
+ ///
+ /// In en, this message translates to:
+ /// **'政府資料開放平臺'**
+ String get dataSourceGovernmentOpenData;
+
+ /// No description provided for @dataSourceOpenStreetMap.
+ ///
+ /// In en, this message translates to:
+ /// **'© OpenStreetMap contributors'**
+ String get dataSourceOpenStreetMap;
+
+ /// No description provided for @dataSourceNasaMoon.
+ ///
+ /// In en, this message translates to:
+ /// **'National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)'**
+ String get dataSourceNasaMoon;
+
+ /// How many of the OSM layers are enabled
+ ///
+ /// In en, this message translates to:
+ /// **'{enabled} of {total} layers enabled'**
+ String mapOsmDetailsHint(int enabled, int total);
+
+ /// No description provided for @mapOsmSurface.
+ ///
+ /// In en, this message translates to:
+ /// **'Surface'**
+ String get mapOsmSurface;
+
+ /// No description provided for @mapOsmParks.
+ ///
+ /// In en, this message translates to:
+ /// **'Parks'**
+ String get mapOsmParks;
+
+ /// No description provided for @mapOsmLandUse.
+ ///
+ /// In en, this message translates to:
+ /// **'Land use'**
+ String get mapOsmLandUse;
+
+ /// No description provided for @mapOsmAirportAreas.
+ ///
+ /// In en, this message translates to:
+ /// **'Airport areas'**
+ String get mapOsmAirportAreas;
+
+ /// No description provided for @mapOsmWater.
+ ///
+ /// In en, this message translates to:
+ /// **'Water'**
+ String get mapOsmWater;
+
+ /// No description provided for @mapOsmRivers.
+ ///
+ /// In en, this message translates to:
+ /// **'Rivers'**
+ String get mapOsmRivers;
+
+ /// No description provided for @mapOsmBoundaries.
+ ///
+ /// In en, this message translates to:
+ /// **'Boundaries'**
+ String get mapOsmBoundaries;
+
+ /// No description provided for @mapOsmBuildings.
+ ///
+ /// In en, this message translates to:
+ /// **'Buildings'**
+ String get mapOsmBuildings;
+
+ /// No description provided for @mapOsmRoads.
+ ///
+ /// In en, this message translates to:
+ /// **'Roads'**
+ String get mapOsmRoads;
+
+ /// No description provided for @mapOsmRoadNames.
+ ///
+ /// In en, this message translates to:
+ /// **'Road names'**
+ String get mapOsmRoadNames;
+
+ /// No description provided for @mapOsmWaterNames.
+ ///
+ /// In en, this message translates to:
+ /// **'Water names'**
+ String get mapOsmWaterNames;
+
+ /// No description provided for @mapOsmPeaks.
+ ///
+ /// In en, this message translates to:
+ /// **'Peaks'**
+ String get mapOsmPeaks;
+
+ /// No description provided for @mapOsmAirportNames.
+ ///
+ /// In en, this message translates to:
+ /// **'Airport names'**
+ String get mapOsmAirportNames;
+
+ /// No description provided for @mapOsmPlaceNames.
+ ///
+ /// In en, this message translates to:
+ /// **'Place names'**
+ String get mapOsmPlaceNames;
+
+ /// No description provided for @mapOsmPoi.
+ ///
+ /// In en, this message translates to:
+ /// **'Points of interest'**
+ String get mapOsmPoi;
+
+ /// No description provided for @mapOsmHouseNumbers.
+ ///
+ /// In en, this message translates to:
+ /// **'House numbers'**
+ String get mapOsmHouseNumbers;
+
+ /// No description provided for @mapOsmRestoreAll.
+ ///
+ /// In en, this message translates to:
+ /// **'Restore all'**
+ String get mapOsmRestoreAll;
+
+ /// No description provided for @mapOsmSectionNatural.
+ ///
+ /// In en, this message translates to:
+ /// **'Natural features'**
+ String get mapOsmSectionNatural;
+
+ /// No description provided for @mapOsmSectionRoadsAndBuildings.
+ ///
+ /// In en, this message translates to:
+ /// **'Roads & buildings'**
+ String get mapOsmSectionRoadsAndBuildings;
+
+ /// No description provided for @mapOsmSectionLabelsAndPlaces.
+ ///
+ /// In en, this message translates to:
+ /// **'Labels & places'**
+ String get mapOsmSectionLabelsAndPlaces;
+
/// Map setting: show township-name labels when the map is zoomed in
///
/// In en, this message translates to:
@@ -5475,6 +5687,78 @@ abstract class AppLocalizations {
/// **'“{what}” was declined, and the system will not ask again. Turn it on in Settings.'**
String permissionSettingsMessage(String what);
+ /// No description provided for @permissionGuideNotification.
+ ///
+ /// In en, this message translates to:
+ /// **'Open System Settings to allow notifications.'**
+ String get permissionGuideNotification;
+
+ /// No description provided for @permissionGuideForegroundLocation.
+ ///
+ /// In en, this message translates to:
+ /// **'Open System Settings to allow precise location.'**
+ String get permissionGuideForegroundLocation;
+
+ /// Instruction for background location
+ ///
+ /// In en, this message translates to:
+ /// **'In “{option}”, choose “Allow all the time”.'**
+ String permissionGuideBackgroundLocation(Object option);
+
+ /// No description provided for @permissionGuideBackgroundExecution.
+ ///
+ /// In en, this message translates to:
+ /// **'Allow background execution in System Settings so notifications are not paused.'**
+ String get permissionGuideBackgroundExecution;
+
+ /// No description provided for @permissionGuideUnusedPause.
+ ///
+ /// In en, this message translates to:
+ /// **'If the app is marked “unused”, choose “Allow” in System Settings.'**
+ String get permissionGuideUnusedPause;
+
+ /// No description provided for @permissionGuideUnusedFreeSpace.
+ ///
+ /// In en, this message translates to:
+ /// **'If the app was paused for storage, clear cache and reopen it.'**
+ String get permissionGuideUnusedFreeSpace;
+
+ /// No description provided for @permissionGuideUnusedRevoke.
+ ///
+ /// In en, this message translates to:
+ /// **'If the app\'s permissions were revoked, grant them again in System Settings.'**
+ String get permissionGuideUnusedRevoke;
+
+ /// No description provided for @permissionGuideUnusedPlayProtect.
+ ///
+ /// In en, this message translates to:
+ /// **'If Play Protect paused the app, check its status in Google Play.'**
+ String get permissionGuideUnusedPlayProtect;
+
+ /// Instruction for vendor power saving
+ ///
+ /// In en, this message translates to:
+ /// **'In “{vendor}” power-saving settings, set this app to “Unrestricted”.'**
+ String permissionGuideVendorPower(Object vendor);
+
+ /// No description provided for @permissionStillRequired.
+ ///
+ /// In en, this message translates to:
+ /// **'Still needs attention. Check the highlighted option in Settings.'**
+ String get permissionStillRequired;
+
+ /// No description provided for @permissionVerifyManually.
+ ///
+ /// In en, this message translates to:
+ /// **'Please verify this permission is enabled in System Settings.'**
+ String get permissionVerifyManually;
+
+ /// No description provided for @permissionBackgroundLocationOption.
+ ///
+ /// In en, this message translates to:
+ /// **'“Allow all the time”'**
+ String get permissionBackgroundLocationOption;
+
/// Display settings: text size section header
///
/// In en, this message translates to:
@@ -5745,6 +6029,24 @@ abstract class AppLocalizations {
/// **'Uploads them and copies a link to paste into a report'**
String get moreDumpDiagnosticsHint;
+ /// Unchecked-by-default consent for private diagnostics
+ ///
+ /// In en, this message translates to:
+ /// **'Include precise location'**
+ String get dumpIncludeSensitive;
+
+ /// Explains which diagnostics require explicit consent
+ ///
+ /// In en, this message translates to:
+ /// **'Includes coordinates from logs and background location; otherwise they are replaced with null'**
+ String get dumpIncludeSensitiveHint;
+
+ /// Button that confirms a diagnostics upload
+ ///
+ /// In en, this message translates to:
+ /// **'Upload'**
+ String get dumpUpload;
+
/// Title of the dialog shown after a debug dump uploads
///
/// In en, this message translates to:
@@ -5800,6 +6102,7 @@ class _AppLocalizationsDelegate
'ko',
'th',
'vi',
+ 'yue',
'zh',
].contains(locale.languageCode);
@@ -5854,6 +6157,8 @@ AppLocalizations lookupAppLocalizations(Locale locale) {
return AppLocalizationsTh();
case 'vi':
return AppLocalizationsVi();
+ case 'yue':
+ return AppLocalizationsYue();
case 'zh':
return AppLocalizationsZh();
}
diff --git a/lib/l10n/gen/app_localizations_en.dart b/lib/l10n/gen/app_localizations_en.dart
index 18479d5c9..f076ce13a 100644
--- a/lib/l10n/gen/app_localizations_en.dart
+++ b/lib/l10n/gen/app_localizations_en.dart
@@ -2129,10 +2129,16 @@ class AppLocalizationsEn extends AppLocalizations {
String get moreVersionStable => 'Release';
@override
- String get moreVersionNotes => 'This version';
+ String get moreVersionNotes => 'This update';
@override
- String get releaseHighlightsTitle => 'What changed in this release';
+ String get moreVersionNotesHighlightsSubtitle =>
+ 'What changed in this release';
+
+ @override
+ String releaseHighlightsTitle(Object train) {
+ return '$train key highlights';
+ }
@override
String get releaseHighlightsTabNormal => 'For users';
@@ -2311,6 +2317,114 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get onboardingTermsTitle => 'Terms of Service';
+ @override
+ String get mapOsmOverlay => 'Detailed map';
+
+ @override
+ String get mapOsmOverlayHint =>
+ 'Show more complete roads, buildings, and place labels';
+
+ @override
+ String get mapOsmDetails => 'Detailed map layers';
+
+ @override
+ String get moreDataSources => 'Data sources';
+
+ @override
+ String get dataSourceTremNet => '探索智慧科技有限公司 — TREM-Net';
+
+ @override
+ String get dataSourceCwa => '交通部中央氣象署 (CWA)';
+
+ @override
+ String get dataSourceJma => '気象庁 (JMA)';
+
+ @override
+ String get dataSourceNcdr => '國家災害防救科技中心 (NCDR)';
+
+ @override
+ String get dataSourceEcmwf =>
+ 'European Centre for Medium-Range Weather Forecasts (ECMWF)';
+
+ @override
+ String get dataSourceNoaaGfs =>
+ 'National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)';
+
+ @override
+ String get dataSourceGovernmentOpenData => '政府資料開放平臺';
+
+ @override
+ String get dataSourceOpenStreetMap => '© OpenStreetMap contributors';
+
+ @override
+ String get dataSourceNasaMoon =>
+ 'National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)';
+
+ @override
+ String mapOsmDetailsHint(int enabled, int total) {
+ return '$enabled of $total layers enabled';
+ }
+
+ @override
+ String get mapOsmSurface => 'Surface';
+
+ @override
+ String get mapOsmParks => 'Parks';
+
+ @override
+ String get mapOsmLandUse => 'Land use';
+
+ @override
+ String get mapOsmAirportAreas => 'Airport areas';
+
+ @override
+ String get mapOsmWater => 'Water';
+
+ @override
+ String get mapOsmRivers => 'Rivers';
+
+ @override
+ String get mapOsmBoundaries => 'Boundaries';
+
+ @override
+ String get mapOsmBuildings => 'Buildings';
+
+ @override
+ String get mapOsmRoads => 'Roads';
+
+ @override
+ String get mapOsmRoadNames => 'Road names';
+
+ @override
+ String get mapOsmWaterNames => 'Water names';
+
+ @override
+ String get mapOsmPeaks => 'Peaks';
+
+ @override
+ String get mapOsmAirportNames => 'Airport names';
+
+ @override
+ String get mapOsmPlaceNames => 'Place names';
+
+ @override
+ String get mapOsmPoi => 'Points of interest';
+
+ @override
+ String get mapOsmHouseNumbers => 'House numbers';
+
+ @override
+ String get mapOsmRestoreAll => 'Restore all';
+
+ @override
+ String get mapOsmSectionNatural => 'Natural features';
+
+ @override
+ String get mapOsmSectionRoadsAndBuildings => 'Roads & buildings';
+
+ @override
+ String get mapOsmSectionLabelsAndPlaces => 'Labels & places';
+
@override
String get mapTownLabels => 'Township names';
@@ -2859,6 +2973,55 @@ class AppLocalizationsEn extends AppLocalizations {
return '“$what” was declined, and the system will not ask again. Turn it on in Settings.';
}
+ @override
+ String get permissionGuideNotification =>
+ 'Open System Settings to allow notifications.';
+
+ @override
+ String get permissionGuideForegroundLocation =>
+ 'Open System Settings to allow precise location.';
+
+ @override
+ String permissionGuideBackgroundLocation(Object option) {
+ return 'In “$option”, choose “Allow all the time”.';
+ }
+
+ @override
+ String get permissionGuideBackgroundExecution =>
+ 'Allow background execution in System Settings so notifications are not paused.';
+
+ @override
+ String get permissionGuideUnusedPause =>
+ 'If the app is marked “unused”, choose “Allow” in System Settings.';
+
+ @override
+ String get permissionGuideUnusedFreeSpace =>
+ 'If the app was paused for storage, clear cache and reopen it.';
+
+ @override
+ String get permissionGuideUnusedRevoke =>
+ 'If the app\'s permissions were revoked, grant them again in System Settings.';
+
+ @override
+ String get permissionGuideUnusedPlayProtect =>
+ 'If Play Protect paused the app, check its status in Google Play.';
+
+ @override
+ String permissionGuideVendorPower(Object vendor) {
+ return 'In “$vendor” power-saving settings, set this app to “Unrestricted”.';
+ }
+
+ @override
+ String get permissionStillRequired =>
+ 'Still needs attention. Check the highlighted option in Settings.';
+
+ @override
+ String get permissionVerifyManually =>
+ 'Please verify this permission is enabled in System Settings.';
+
+ @override
+ String get permissionBackgroundLocationOption => '“Allow all the time”';
+
@override
String get displayTextSize => 'Text size';
@@ -3006,6 +3169,16 @@ class AppLocalizationsEn extends AppLocalizations {
String get moreDumpDiagnosticsHint =>
'Uploads them and copies a link to paste into a report';
+ @override
+ String get dumpIncludeSensitive => 'Include precise location';
+
+ @override
+ String get dumpIncludeSensitiveHint =>
+ 'Includes coordinates from logs and background location; otherwise they are replaced with null';
+
+ @override
+ String get dumpUpload => 'Upload';
+
@override
String get dumpUploaded => 'Uploaded';
diff --git a/lib/l10n/gen/app_localizations_fil.dart b/lib/l10n/gen/app_localizations_fil.dart
index 4d4aec4fd..5c66846f1 100644
--- a/lib/l10n/gen/app_localizations_fil.dart
+++ b/lib/l10n/gen/app_localizations_fil.dart
@@ -47,7 +47,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get mapLayerSatelliteB03 => 'Himawari Red (B03)';
@override
- String get reportFilterIntensity => 'Intensity';
+ String get reportFilterIntensity => 'Lakas';
@override
String get mapLayerLightning => 'Kidlat';
@@ -56,7 +56,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get restroomTypeMale => 'Palikuran ng lalaki';
@override
- String get meshtasticLastReceived => 'Last received';
+ String get meshtasticLastReceived => 'Huling natanggap';
@override
String get reportDetailSortByCounty => 'Ayusin ayon sa lalawigan';
@@ -87,7 +87,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get homeRainTrendScattered => 'Posibleng mahinang ulan';
@override
- String get meshtasticUptime => 'Uptime';
+ String get meshtasticUptime => 'Oras ng pagtakbo';
@override
String get weatherRankingTempExtremes => 'Mga sukdulan ng temperatura';
@@ -99,7 +99,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get mapTerrainReliefHint => 'Ipakita ang anino ng terrain sa base map';
@override
- String get meshtasticEmptyMessage => '(empty message)';
+ String get meshtasticEmptyMessage => '(walang laman na mensahe)';
@override
String get moreSectionRegion => 'Rehiyon';
@@ -111,7 +111,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get aedHoursSaturday => 'Oras sa Sabado';
@override
- String get moonPhaseNew => 'New moon';
+ String get moonPhaseNew => 'Bagong buwan';
@override
String get notifySectionEew => 'Maagang babala sa lindol';
@@ -127,7 +127,7 @@ class AppLocalizationsFil extends AppLocalizations {
'Ipakita ang mga pangalan ng bayan kapag naka-zoom';
@override
- String get commonCancel => 'Cancel';
+ String get commonCancel => 'Kanselahin';
@override
String get notifyOptTsunamiWarning => 'Mga babala sa tsunami lamang';
@@ -136,7 +136,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get mapLayerSatelliteBtdFog => 'Himawari Night Fog';
@override
- String get moreSectionAdvanced => 'Advanced';
+ String get moreSectionAdvanced => 'Mas advanced';
@override
String get moreSectionMesh => 'Mesh network';
@@ -167,7 +167,7 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get mapLayerStyleJmaTooltip =>
- 'Grayscale base, tinted below −40 °C to highlight cloud-top height';
+ 'Grayscale na base, may kulay sa ibaba ng −40 °C para i-highlight ang taas ng ulap';
@override
String get mapLayerRain => 'Ulan';
@@ -221,7 +221,7 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get meshtasticExcludeMqttSubtitle =>
- 'Nodes bridged over the internet, not heard by radio';
+ 'Mga node na konektado sa internet, hindi naririnig sa radyo';
@override
String get reportFilterIntensityInfoTitle =>
@@ -234,14 +234,14 @@ class AppLocalizationsFil extends AppLocalizations {
String get radarOverlayMenuTooltip => 'Mga opsyon sa layer ng radar';
@override
- String get meshtasticNodes => 'Nodes';
+ String get meshtasticNodes => 'Mga node';
@override
- String get meshtasticSend => 'Send';
+ String get meshtasticSend => 'Ipadala';
@override
String get typhoonOverlayStormL7Tooltip =>
- 'Level-7 wind field + average circle (purple)';
+ 'Larangan ng hangin sa antas 7 + average circle (lila)';
@override
String get aedType => 'Uri';
@@ -302,7 +302,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get reportFilterSortMagnitude => 'Magnitude';
@override
- String get meshtasticSilent => 'Silent';
+ String get meshtasticSilent => 'Tahimik';
@override
String get mapLayerCategoryEarthquake => 'Lindol';
@@ -336,7 +336,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get notifyOptTsunamiAll => 'Mga abiso at babala sa tsunami';
@override
- String get meshtasticLayerOptions => 'Node options';
+ String get meshtasticLayerOptions => 'Mga opsyon sa node';
@override
String get onboardingAgreeContinue => 'Sumang-ayon at magpatuloy';
@@ -353,7 +353,7 @@ class AppLocalizationsFil extends AppLocalizations {
}
@override
- String get typhoonOverlayStormBandSubtitle => 'With average circle';
+ String get typhoonOverlayStormBandSubtitle => 'May average circle';
@override
String get disasterMapOverlayRestroomTooltip =>
@@ -382,30 +382,30 @@ class AppLocalizationsFil extends AppLocalizations {
String get sponsorRestore => 'Ibalik ang mga pagbili';
@override
- String get meshtasticChannelWorking => 'Setting up the DPIP channel…';
+ String get meshtasticChannelWorking => 'Ini-set up ang DPIP channel…';
@override
- String get meshtasticRegionSwitch => 'Switch to TW';
+ String get meshtasticRegionSwitch => 'Lumipat sa TW';
@override
- String get meshtasticTraffic => 'Traffic';
+ String get meshtasticTraffic => 'Trapiko';
@override
String get mapLayerStyleBdTooltip =>
- 'Dvorak BD curve — the stepped grayscale for tropical-cyclone intensity analysis';
+ 'Dvorak BD curve — ang stepped grayscale para sa pagsusuri ng lakas ng bagyo';
@override
- String get disasterMapOverlayAedTooltip => 'Show AED locations';
+ String get disasterMapOverlayAedTooltip => 'Ipakita ang mga lokasyon ng AED';
@override
String get mapLayerHumidity => 'Halumigmig';
@override
String get mapLayerSatelliteTransparentNight =>
- 'Night = transparent, the basemap shows';
+ 'Gabing transparent, makikita ang basemap';
@override
- String get meshtasticScanning => 'Scanning…';
+ String get meshtasticScanning => 'Nag-scan…';
@override
String regionSelectFull(int max) {
@@ -480,7 +480,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get meshtasticDpipChannel => 'DPIP channel';
@override
- String get disasterMapOverlaySectionLayers => 'Layers';
+ String get disasterMapOverlaySectionLayers => 'Mga layer';
@override
String get mapLayerSatelliteB05 => 'Himawari Near-Infrared (B05)';
@@ -489,7 +489,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get typhoonLabelNe => 'NE';
@override
- String get meshtasticCopied => 'Message copied';
+ String get meshtasticCopied => 'Nakopya ang mensahe';
@override
String get reportListEmpty => 'Walang ulat ng lindol';
@@ -501,19 +501,19 @@ class AppLocalizationsFil extends AppLocalizations {
String get mapLayerSatelliteTruecolor => 'Himawari True Color';
@override
- String get typhoonOverlaySectionExtra => 'Overlays';
+ String get typhoonOverlaySectionExtra => 'Mga overlay';
@override
String get eewSWave => 'S wave';
@override
- String get meshtasticBusyTitle => 'Another app is using this radio';
+ String get meshtasticBusyTitle => 'May ibang app na gumagamit ng radyong ito';
@override
String get restroomCategoryCultural => 'Pook na pangkultura';
@override
- String get typhoonLabelWind => 'Max. sustained wind near centre';
+ String get typhoonLabelWind => 'Max. sustained wind malapit sa gitna';
@override
String get radarGlobalOutlineHint => 'Panlabas na balangkas ng bawat bansa';
@@ -525,7 +525,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get typhoonLegendCircle15 => 'Gale circle (L7)';
@override
- String get dataSectionAstronomy => 'Astronomy';
+ String get dataSectionAstronomy => 'Astronomiya';
@override
String get homeRainTrendLightSustained =>
@@ -535,10 +535,10 @@ class AppLocalizationsFil extends AppLocalizations {
String get commonError => 'May Nangyaring Mali';
@override
- String get moonPhaseWaningCrescent => 'Waning crescent';
+ String get moonPhaseWaningCrescent => 'Lumiit na gasuklay';
@override
- String get meshtasticPower => 'Power';
+ String get meshtasticPower => 'Kuryente';
@override
String get mapTimelineNow => 'Ngayon';
@@ -556,7 +556,7 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String typhoonWarningAreas(String areas) {
- return 'Areas: $areas';
+ return 'Mga lugar: $areas';
}
@override
@@ -579,7 +579,7 @@ class AppLocalizationsFil extends AppLocalizations {
'Nakatuon ang DPIP sa pagbibigay ng real-time na impormasyon sa pag-iwas sa sakuna, nang walang ad o iba pang modelo ng kita. Tumutulong ang inyong suporta na mapanatili ang mga server at magpatuloy sa pagbuo.';
@override
- String get typhoonLabelStormAvg => 'Avg. radius of Beaufort 10 winds';
+ String get typhoonLabelStormAvg => 'Avg. radius ng Beaufort 10 na hangin';
@override
String get restroomCategoryCommercial => 'Komersyal na establisyimento';
@@ -614,10 +614,10 @@ class AppLocalizationsFil extends AppLocalizations {
String get restroomTypeUnspecified => 'Hindi natukoy';
@override
- String get typhoonOverlayProbabilityHint => 'Hides the forecast cone';
+ String get typhoonOverlayProbabilityHint => 'Itinatago ang forecast cone';
@override
- String get mapLayerSatelliteGlobalOutline => 'Country border';
+ String get mapLayerSatelliteGlobalOutline => 'Border ng bansa';
@override
String get mapNavTemperature => 'Temperatura';
@@ -652,7 +652,7 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get typhoonOverlayWeatherRadarTooltip =>
- 'Radar echo closest to the typhoon bulletin time';
+ 'Radar echo na pinakamalapit sa oras ng bulletin ng bagyo';
@override
String get onboardingPermLocationDesc =>
@@ -665,13 +665,13 @@ class AppLocalizationsFil extends AppLocalizations {
String get homeActiveEventsEmpty => 'Walang aktibong event';
@override
- String get typhoonLabelPosition => 'Centre location';
+ String get typhoonLabelPosition => 'Lokasyon ng gitna';
@override
String get weatherRankingBy => 'Ayon sa';
@override
- String get typhoonIntensityMild => 'Mild typhoon';
+ String get typhoonIntensityMild => 'Mahinang bagyo';
@override
String get windForecastGlobalOutlineHint =>
@@ -693,16 +693,16 @@ class AppLocalizationsFil extends AppLocalizations {
String get meshtasticRole => 'Role';
@override
- String get mapLayerSatelliteCloudCloudy => 'Cloudy';
+ String get mapLayerSatelliteCloudCloudy => 'Maulap';
@override
- String get skyTimeSunrise => 'Pagsikat ng araw';
+ String get skyTimeSunrise => 'Paosmkat ng araw';
@override
String get meshtasticJumpToLatest => 'Pumunta sa pinakabago';
@override
- String get meshtasticNoMessages => 'No messages yet';
+ String get meshtasticNoMessages => 'Wala pang mensahe';
@override
String get onboardingPermNotifyDesc =>
@@ -712,16 +712,16 @@ class AppLocalizationsFil extends AppLocalizations {
String get radarTownOutline => 'Mga hangganan ng bayan';
@override
- String get mapLayerStyleSection => 'Colour style';
+ String get mapLayerStyleSection => 'Estilo ng kulay';
@override
- String get disasterMapOverlayMenuTooltip => 'Disaster map layers';
+ String get disasterMapOverlayMenuTooltip => 'Mga layer ng disaster map';
@override
String get moreGooglePlay => 'Google Play';
@override
- String get meshtasticOnline => 'Heard recently';
+ String get meshtasticOnline => 'Kamakailang narinig';
@override
String get typhoonLabelSw => 'SW';
@@ -736,7 +736,7 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentClear =>
- 'Clear sky = transparent, the basemap shows';
+ 'Maaliwalas = transparent, makikita ang basemap';
@override
String get mapOverlaySectionReference => 'Layer ng sanggunian';
@@ -761,7 +761,7 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentNoVegetation =>
- 'Below 0.1 = transparent (no vegetation)';
+ 'Sa ibaba ng 0.1 = transparent (walang vegetation)';
@override
String get notifyOptLocalIntensity4 => 'Lokal na intensidad 4 pataas';
@@ -770,19 +770,19 @@ class AppLocalizationsFil extends AppLocalizations {
String get eewArrived => 'Dumating';
@override
- String get meshtasticNoDevices => 'No Meshtastic devices found';
+ String get meshtasticNoDevices => 'Walang nahanap na Meshtastic device';
@override
String get mapLayerCategoryLife => 'Pang-araw-araw na buhay';
@override
- String get reportFilterSortIntensity => 'Intensity';
+ String get reportFilterSortIntensity => 'Lakas';
@override
- String get meshtasticStateDisconnected => 'Disconnected';
+ String get meshtasticStateDisconnected => 'Naka-disconnect';
@override
- String get typhoonIntensityIntense => 'Intense typhoon';
+ String get typhoonIntensityIntense => 'Malakas na bagyo';
@override
String get mapLayerOrderTitle => 'Ayusin ang ayos ng layer';
@@ -791,7 +791,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get dpmYes => 'Oo';
@override
- String get meshtasticNoHistory => 'Not enough history yet';
+ String get meshtasticNoHistory => 'Kulang pa sa history';
@override
String get reportDetailLocalIntensityUnavailable =>
@@ -801,7 +801,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get mapLayerWindForecastGfs => 'GFS';
@override
- String get reportFilterDepth => 'Depth';
+ String get reportFilterDepth => 'Lalim';
@override
String get onboardingScrollHint => 'Mag-scroll pababa para magpatuloy';
@@ -819,10 +819,10 @@ class AppLocalizationsFil extends AppLocalizations {
String get mapLayerSatelliteMndwi => 'Himawari MNDWI';
@override
- String get typhoonOverlaySectionStorm => 'Storm wind';
+ String get typhoonOverlaySectionStorm => 'Hanging bagyo';
@override
- String get moonPhaseFull => 'Full moon';
+ String get moonPhaseFull => 'Kabilugan ng buwan';
@override
String meshtasticBinaryPayload(String size) {
@@ -830,14 +830,14 @@ class AppLocalizationsFil extends AppLocalizations {
}
@override
- String get moonPhaseWaningGibbous => 'Waning gibbous';
+ String get moonPhaseWaningGibbous => 'Humihinang bilog';
@override
String get reportFilterIntensityInfoModernTitle => 'Bago (mula 2020)';
@override
String typhoonDataTime(String time) {
- return 'Data time\n$time';
+ return 'Oras ng datos';
}
@override
@@ -847,7 +847,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get moreSectionAbout => 'Tungkol';
@override
- String get meshtasticSelectDevice => 'Select a radio';
+ String get meshtasticSelectDevice => 'Pumili ng radyo';
@override
String get onboardingIntroBody =>
@@ -860,19 +860,19 @@ class AppLocalizationsFil extends AppLocalizations {
String get reportDetailImage => 'Larawan ng Ulat';
@override
- String get meshtasticStateConfiguring => 'Configuring…';
+ String get meshtasticStateConfiguring => 'Kino-configure…';
@override
- String get typhoonLabelGaleAvg => 'Avg. radius of Beaufort 7 winds';
+ String get typhoonLabelGaleAvg => 'Avg. radius ng Beaufort 7 na hangin';
@override
String get onboardingPermNotify => 'Mga Notipikasyon';
@override
- String get meshtasticClearMessages => 'Clear messages';
+ String get meshtasticClearMessages => 'I-clear ang mga mensahe';
@override
- String get meshtasticNotifyMessages => 'Notify on new messages';
+ String get meshtasticNotifyMessages => 'Mag-notify sa mga bagong mensahe';
@override
String get defaultMapLayerSettings => 'Default na layer ng mapa';
@@ -970,7 +970,7 @@ class AppLocalizationsFil extends AppLocalizations {
}
@override
- String get typhoonLabelGust => 'Peak gust';
+ String get typhoonLabelGust => 'Pinakamalakas na bugso';
@override
String get mapAppGoogleMaps => 'Google Maps';
@@ -988,7 +988,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get skyTimeGolden => 'Gintong oras';
@override
- String get moonAge => 'Age';
+ String get moonAge => 'Edad ng buwan';
@override
String get meshtasticRadioSettings => 'LoRa';
@@ -1018,7 +1018,7 @@ class AppLocalizationsFil extends AppLocalizations {
}
@override
- String get typhoonOverlayWeatherHint => 'Aligned to bulletin time';
+ String get typhoonOverlayWeatherHint => 'Naka-align sa oras ng bulletin';
@override
String get skyTimeDawn => 'Bukang-liwayway';
@@ -1027,10 +1027,10 @@ class AppLocalizationsFil extends AppLocalizations {
String get skyTimeAfternoon => 'Hapon';
@override
- String get meshtasticLastHeard => 'Last heard';
+ String get meshtasticLastHeard => 'Huling narinig';
@override
- String get typhoonWarningTitle => 'Typhoon warning';
+ String get typhoonWarningTitle => 'Babala ng bagyo';
@override
String get moreSourceCode => 'Source code';
@@ -1078,10 +1078,10 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get typhoonOverlayStormL10Tooltip =>
- 'Level-10 wind field + average circle (yellow)';
+ 'Larangan ng hangin sa antas 10 + average circle (dilaw)';
@override
- String get moonPhaseWaxingGibbous => 'Waxing gibbous';
+ String get moonPhaseWaxingGibbous => 'Lumalaking bilog';
@override
String get reportDetailTitle => 'Ulat ng Lindol';
@@ -1095,10 +1095,10 @@ class AppLocalizationsFil extends AppLocalizations {
}
@override
- String get meshtasticNoNodes => 'No nodes heard yet';
+ String get meshtasticNoNodes => 'Wala pang narinig na node';
@override
- String get meshtasticViaMqtt => 'Via MQTT (internet)';
+ String get meshtasticViaMqtt => 'Sa pamamagitan ng MQTT (internet)';
@override
String get radarCountyOutline => 'Mga hangganan ng lalawigan';
@@ -1120,7 +1120,7 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get typhoonOverlayForecastCalloutsTooltip =>
- 'Show forecast-point detail cards when zoomed in';
+ 'Ipakita ang mga detalye ng forecast point kapag naka-zoom';
@override
String get aedOpenRemark => 'Tala sa oras';
@@ -1139,7 +1139,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get mapNavRain => 'Ulan';
@override
- String get moonDays => 'days';
+ String get moonDays => 'araw';
@override
String mapLegendUnit(String unit) {
@@ -1150,7 +1150,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get weatherModeClear => 'Maaliwalas';
@override
- String get meshtasticRadio => 'Radio';
+ String get meshtasticRadio => 'Radyo';
@override
String get commonEmpty => 'Walang Maipakita';
@@ -1159,10 +1159,10 @@ class AppLocalizationsFil extends AppLocalizations {
String get mapLayerSatelliteB01 => 'Himawari Blue (B01)';
@override
- String get meshtasticExternalPower => 'External power';
+ String get meshtasticExternalPower => 'Panlabas na kuryente';
@override
- String get moonPhaseLastQuarter => 'Last quarter';
+ String get moonPhaseLastQuarter => 'Huling sangkapat';
@override
String get reportFilterOrderAsc => 'Pataas';
@@ -1190,19 +1190,19 @@ class AppLocalizationsFil extends AppLocalizations {
String get restroomGradeExcellent => 'Napakahusay';
@override
- String get meshtasticLastSent => 'Last sent';
+ String get meshtasticLastSent => 'Huling ipinadala';
@override
- String get meshtasticName => 'Name';
+ String get meshtasticName => 'Pangalan';
@override
- String get meshtasticScan => 'Scan';
+ String get meshtasticScan => 'I-scan';
@override
String get mapLayerCategoryForecast => 'Numerical forecast';
@override
- String get meshtasticChannelFailed => 'Couldn\'t set up the DPIP channel';
+ String get meshtasticChannelFailed => 'Hindi ma-set up ang DPIP channel';
@override
String get themeSystem => 'Sistema';
@@ -1222,7 +1222,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get weatherPrecipitation => 'Pag-ulan';
@override
- String get moonNextFullMoon => 'Next full moon';
+ String get moonNextFullMoon => 'Susunod na kabilugan';
@override
String get dpmSheetEmpty => 'I-tap ang marker sa mapa para sa detalye';
@@ -1251,7 +1251,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get typhoonLabelNw => 'NW';
@override
- String get moonPhaseWaxingCrescent => 'Waxing crescent';
+ String get moonPhaseWaxingCrescent => 'Lumalaking gasuklay';
@override
String get restroomCategoryLeisure => 'Lugar ng libangan';
@@ -1263,7 +1263,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get aedCategory => 'Kategorya';
@override
- String get meshtasticChannels => 'Channels';
+ String get meshtasticChannels => 'Mga channel';
@override
String get monitorWaiting => 'Naghihintay ng data…';
@@ -1275,11 +1275,11 @@ class AppLocalizationsFil extends AppLocalizations {
String get reportDetailEpicenter => 'Coordinates ng Epicenter';
@override
- String get meshtasticVoltage => 'Voltage';
+ String get meshtasticVoltage => 'Boltahe';
@override
String get mapLayerMeshtasticSubtitle =>
- 'LoRa mesh nodes heard by your radio';
+ 'LoRa mesh nodes na narinig ng radyo mo';
@override
String get mapLayerWind => 'Hangin';
@@ -1302,7 +1302,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get notifyMonitor => 'Monitor ng malakas na paggalaw';
@override
- String get onboardingStart => 'Magsimula';
+ String get onboardingStart => 'Maosmmula';
@override
String sponsorPerMonth(String price) {
@@ -1317,7 +1317,7 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentZero =>
- 'Zero difference = transparent (no signal)';
+ 'Zero difference = transparent (walang signal)';
@override
String get shelterIndoorLabel => 'Silungan sa loob';
@@ -1329,7 +1329,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get reportFilterSortTime => 'Oras';
@override
- String get mapLayerSatelliteCloudProbablyClear => 'Probably clear';
+ String get mapLayerSatelliteCloudProbablyClear => 'Malamang maaliwalas';
@override
String get weatherModeThunderstorm => 'Kulog at Kidlat';
@@ -1341,7 +1341,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get reportFilterIntensityInfoLegacyTitle => 'Luma (bago ang 2020)';
@override
- String get typhoonLabelSpeed => 'Past movement speed';
+ String get typhoonLabelSpeed => 'Bilis ng paggalaw';
@override
String mapAppOpenFailed(String app) {
@@ -1352,7 +1352,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get mapLayerSatelliteRgbComposite => 'RGB composite (JMA recipe)';
@override
- String get meshtasticReceived => 'Received';
+ String get meshtasticReceived => 'Natanggap';
@override
String get weatherRankingExtremeLow => 'Pinakamababa ngayong araw';
@@ -1361,20 +1361,20 @@ class AppLocalizationsFil extends AppLocalizations {
String get mapLayerSatelliteB10 => 'Himawari Lower Water Vapour (B10)';
@override
- String get mapLayerSatelliteCloudProbablyCloudy => 'Probably cloudy';
+ String get mapLayerSatelliteCloudProbablyCloudy => 'Malamang maulap';
@override
String get mapLayerSatelliteTransparentNoWater =>
- '≤ 0 = transparent (no water)';
+ '≤ 0 = transparent (walang tubig)';
@override
String get shelterCategoryLabel => 'Mga uri ng kalamidad';
@override
- String get meshtasticStateConnecting => 'Connecting…';
+ String get meshtasticStateConnecting => 'Kumokonekta…';
@override
- String get moonTitle => 'Moon';
+ String get moonTitle => 'Buwan';
@override
String get weatherRankingGust => 'Bugso';
@@ -1416,7 +1416,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get regionCurrent => 'Kasalukuyang lokasyon';
@override
- String get meshtasticNotConnected => 'Not connected to a radio';
+ String get meshtasticNotConnected => 'Hindi konektado sa radyo';
@override
String get weatherModeSnow => 'Niyebe';
@@ -1431,7 +1431,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get mapLayerSatelliteB14 => 'Himawari Longwave Infrared (B14)';
@override
- String get meshtasticChannelUse => 'Channel use';
+ String get meshtasticChannelUse => 'Paggamit ng channel';
@override
String get mapNavLightning => 'Kidlat';
@@ -1455,7 +1455,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get dpmOpenInMaps => 'Buksan sa mapa';
@override
- String get meshtasticNotifyNodes => 'Notify on new nodes';
+ String get meshtasticNotifyNodes => 'Mag-notify sa mga bagong node';
@override
String get onboardingPermCriticalDesc =>
@@ -1463,20 +1463,20 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentWarm =>
- 'Clear sky (warm end) = transparent, the basemap shows';
+ 'Maaliwalas (mainit) = transparent, makikita ang basemap';
@override
- String get meshtasticSent => 'Sent';
+ String get meshtasticSent => 'Ipinadala';
@override
String get homeForecastTitle => '24-oras na forecast';
@override
- String get typhoonLegendWarningAreas => 'Warning areas';
+ String get typhoonLegendWarningAreas => 'Mga lugar ng babala';
@override
String meshtasticExcludeMqttHidden(int count) {
- return '$count hidden';
+ return '$count nakatago';
}
@override
@@ -1492,13 +1492,13 @@ class AppLocalizationsFil extends AppLocalizations {
String get reportListToday => 'Ngayon';
@override
- String get meshtasticTapNode => 'Tap a node for details';
+ String get meshtasticTapNode => 'I-tap ang node para sa detalye';
@override
String get commonLoading => 'Naglo-load…';
@override
- String get typhoonIntensityModerate => 'Moderate typhoon';
+ String get typhoonIntensityModerate => 'Katamtamang bagyo';
@override
String get mapLayerSatelliteAsh => 'Himawari Ash';
@@ -1510,7 +1510,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get mapLayerCategorySatellite => 'Satellite';
@override
- String get meshtasticChannelReady => 'DPIP channel ready';
+ String get meshtasticChannelReady => 'Handa na ang DPIP channel';
@override
String get mapLayerSatelliteNightmicrophysics =>
@@ -1602,7 +1602,7 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get typhoonOverlayWarningTooltip =>
- 'Highlight counties under a typhoon warning';
+ 'I-highlight ang mga county sa ilalim ng babala ng bagyo';
@override
String get reportFilterDatePick => 'Pumili ng petsa';
@@ -1617,13 +1617,13 @@ class AppLocalizationsFil extends AppLocalizations {
String get shelterOutdoorLabel => 'Silungan sa labas';
@override
- String get meshtasticStateConnected => 'Connected';
+ String get meshtasticStateConnected => 'Nakakonekta';
@override
String get mapNavRadar => 'Radar';
@override
- String get mapLayerSatelliteCloudClear => 'Clear';
+ String get mapLayerSatelliteCloudClear => 'Maaliwalas';
@override
String eewSummary(String magnitude, String depth) {
@@ -1636,7 +1636,7 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get typhoonOverlayWeatherNoneTooltip =>
- 'No radar or infrared underlay';
+ 'Walang radar o infrared underlay';
@override
String get radarCountyOutlineHint => 'Iginuguhit sa ibabaw ng echo';
@@ -1649,7 +1649,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get homeRainTrendTitle => 'Ulan sa susunod na oras';
@override
- String get moonPhaseFirstQuarter => 'First quarter';
+ String get moonPhaseFirstQuarter => 'Unang sangkapat';
@override
String get mapLayerCategoryTyphoon => 'Bagyo';
@@ -1673,7 +1673,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get mapLayerSatelliteBtdWvirw => 'Himawari Overshooting Top';
@override
- String get meshtasticReadingAge => 'Reading taken';
+ String get meshtasticReadingAge => 'Oras ng pagsukat';
@override
String get mapAppCallFailed => 'Hindi makatawag ang device na ito';
@@ -1743,7 +1743,7 @@ class AppLocalizationsFil extends AppLocalizations {
'Walang ulat na tumutugma sa mga filter';
@override
- String get meshtasticExcludeMqtt => 'Hide MQTT nodes';
+ String get meshtasticExcludeMqtt => 'Itago ang mga MQTT node';
@override
String get mapNavTyphoon => 'Bagyo';
@@ -1774,20 +1774,20 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String homeForecastWind(String direction, String level) {
- return '$direction · Force $level';
+ return '$direction · Lakas $level';
}
@override
String get navHome => 'Tahanan';
@override
- String get meshtasticRegionLabel => 'Region';
+ String get meshtasticRegionLabel => 'Rehiyon';
@override
String get mapLayerSatelliteCloudtop => 'Himawari Cloud Top Temperature';
@override
- String get moonTimelineCaption => 'Phase';
+ String get moonTimelineCaption => 'Porsyento';
@override
String get openSourceLicenses => 'Mga lisensya ng open-source';
@@ -1835,7 +1835,7 @@ class AppLocalizationsFil extends AppLocalizations {
}
@override
- String get meshtasticSendHint => 'Message to broadcast';
+ String get meshtasticSendHint => 'Mensaheng ipapadala';
@override
String monitorDelay(String value) {
@@ -1849,7 +1849,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get mapLayerSatelliteB08 => 'Himawari Upper Water Vapour (B08)';
@override
- String get meshtasticReconnecting => 'Reconnecting…';
+ String get meshtasticReconnecting => 'Kumokonekta ulit…';
@override
String get radarTownOutlineSubtitle =>
@@ -1857,7 +1857,7 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get typhoonOverlayWeatherSatelliteTooltip =>
- 'Infrared closest to the typhoon bulletin time';
+ 'Infrared na pinakamalapit sa oras ng bulletin ng bagyo';
@override
String get radarScanRangeHint => 'Sa labas: hindi naoobserbahan';
@@ -1887,7 +1887,7 @@ class AppLocalizationsFil extends AppLocalizations {
'Naka-off ang mga serbisyo ng lokasyon — hindi matutukoy ng mga lokal na alerto ang iyong lugar.';
@override
- String get mapLayerStyleTooltip => 'Colour style';
+ String get mapLayerStyleTooltip => 'Estilo ng kulay';
@override
String lightningLegendCg(int minutes) {
@@ -2025,40 +2025,40 @@ class AppLocalizationsFil extends AppLocalizations {
String get endpointServiceQpesums => 'QPE';
@override
- String get endpointServiceWind => 'Wind';
+ String get endpointServiceWind => 'Hangin';
@override
String get endpointServiceDpm => 'Disaster points';
@override
- String get endpointServiceWeather => 'Weather';
+ String get endpointServiceWeather => 'Panahon';
@override
- String get endpointServiceRain => 'Rain';
+ String get endpointServiceRain => 'Ulan';
@override
- String get endpointServiceLightning => 'Lightning';
+ String get endpointServiceLightning => 'Kidlat';
@override
- String get endpointServiceTyphoon => 'Typhoon';
+ String get endpointServiceTyphoon => 'Bagyo';
@override
- String get endpointServiceReport => 'EQ reports';
+ String get endpointServiceReport => 'Mga ulat ng lindol';
@override
String get endpointServiceTremStation => 'Tremor station';
@override
- String get endpointServiceEvent => 'Events';
+ String get endpointServiceEvent => 'Mga event';
@override
- String get endpointServiceLocation => 'Location';
+ String get endpointServiceLocation => 'Lokasyon';
@override
- String get endpointServiceNotify => 'Notifications';
+ String get endpointServiceNotify => 'Mga notipikasyon';
@override
- String get endpointServiceOther => 'Other';
+ String get endpointServiceOther => 'Iba pa';
@override
String get feedConnecting => 'Kumokonekta…';
@@ -2082,17 +2082,17 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get meshtasticBusyBody =>
- 'Disconnect it in the other Meshtastic app first. Two apps on one radio take each other\'s messages, so some will go missing.';
+ 'I-disconnect muna ito sa ibang Meshtastic app. Dalawang app sa isang radyo ang nag-aagawan sa mensahe, kaya may mawawala.';
@override
String get meshtasticChannelNoSlot =>
- 'No free channel slot — free one on the radio';
+ 'Walang libreng channel slot — magbakante sa radyo';
@override
String get restroomCategoryTransport => 'Transportasyon';
@override
- String get meshtasticBattery => 'Battery';
+ String get meshtasticBattery => 'Baterya';
@override
String get meshtasticDistance => 'Distansya';
@@ -2104,14 +2104,14 @@ class AppLocalizationsFil extends AppLocalizations {
String get meshtasticBatteryTrend => 'Trend ng baterya';
@override
- String get typhoonOverlayMenuTooltip => 'Typhoon overlay options';
+ String get typhoonOverlayMenuTooltip => 'Mga opsyon sa typhoon overlay';
@override
String get mapLayerSatelliteBtdOzone => 'Himawari Tropopause';
@override
String meshtasticRegionMismatch(String region) {
- return 'Radio region is $region — DPIP needs TW';
+ return 'Ang region ng radyo ay $region — kailangan ng DPIP ang TW';
}
@override
@@ -2129,7 +2129,8 @@ class AppLocalizationsFil extends AppLocalizations {
}
@override
- String get mapLayerStyleGrayTooltip => 'JMA grayscale — colder is whiter';
+ String get mapLayerStyleGrayTooltip =>
+ 'JMA grayscale — mas malamig ay mas puti';
@override
String get moreAnnouncements => 'Mga Anunsyo';
@@ -2142,10 +2143,16 @@ class AppLocalizationsFil extends AppLocalizations {
String get moreVersionStable => 'Pormal na bersyon';
@override
- String get moreVersionNotes => 'Kasalukuyang bersyon';
+ String get moreVersionNotes => 'Update na ito';
@override
- String get releaseHighlightsTitle => 'Ano ang nagbago';
+ String get moreVersionNotesHighlightsSubtitle =>
+ 'Ano ang nagbago sa bersyon na ito';
+
+ @override
+ String releaseHighlightsTitle(Object train) {
+ return '$train buod';
+ }
@override
String get releaseHighlightsTabNormal => 'Para sa mga user';
@@ -2167,7 +2174,7 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentNoData =>
- 'No data (land) = transparent';
+ 'Walang data (lupa) = transparent';
@override
String get restroomCategoryGovernment => 'Opisina ng gobyerno';
@@ -2189,7 +2196,7 @@ class AppLocalizationsFil extends AppLocalizations {
'Antas 0–4, 5−, 5+, 6−, 6+, 7. Gamit ng filter ang bagong scale; ang mga lumang event ay may legacy label sa listahan.';
@override
- String get typhoonOverlayWeatherNone => 'None';
+ String get typhoonOverlayWeatherNone => 'Wala';
@override
String get mapLayerStyleGray => 'Grayscale (JMA)';
@@ -2210,7 +2217,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get mapLayerSatelliteB07 => 'Himawari Shortwave Infrared (B07)';
@override
- String get typhoonLabelDirection => 'Past movement direction';
+ String get typhoonLabelDirection => 'Direksyon ng paggalaw';
@override
String get regionManageTitle => 'Mga naka-save na rehiyon';
@@ -2235,7 +2242,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get rainInterval10m => '10 min';
@override
- String get meshtasticConnectAnyway => 'Connect anyway';
+ String get meshtasticConnectAnyway => 'Kumonekta pa rin';
@override
String reportListDayCount(int count) {
@@ -2247,7 +2254,7 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentReflectance =>
- 'Low reflectance / night = transparent, the basemap shows';
+ 'Mababang reflectance / gabi = transparent, makikita ang basemap';
@override
String chartHourLabel(int hour) {
@@ -2259,7 +2266,7 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get typhoonOverlayProbabilityTooltip =>
- 'Show strike probability (hides the forecast cone)';
+ 'Ipakita ang strike probability (itinatago ang forecast cone)';
@override
String get mapLayerSatelliteNdwi => 'Himawari NDWI';
@@ -2280,7 +2287,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get mapLayerCategoryRadar => 'Radar';
@override
- String get meshtasticShortName => 'Short name';
+ String get meshtasticShortName => 'Maikling pangalan';
@override
String get mapLayerSatelliteAirmass => 'Himawari Airmass';
@@ -2307,7 +2314,7 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get meshtasticRegionConfirm =>
- 'Switch this radio to the TW region? It restarts and disconnects for a moment, and every other channel on it moves too.';
+ 'Lumipat ba ang radyong ito sa TW region? Magre-restart at magdi-disconnect saglit, at lilipat din ang lahat ng ibang channel.';
@override
String get dataEarthquakeSubtitle => 'Mga ulat ng lindol';
@@ -2324,6 +2331,114 @@ class AppLocalizationsFil extends AppLocalizations {
@override
String get onboardingTermsTitle => 'Mga Tuntunin ng Serbisyo';
+ @override
+ String get mapOsmOverlay => 'Detalyadong mapa';
+
+ @override
+ String get mapOsmOverlayHint =>
+ 'Ipakita ang mas kumpletong mga kalsada, gusali, at pangalan ng lugar';
+
+ @override
+ String get mapOsmDetails => 'Mga detalye ng layer';
+
+ @override
+ String get moreDataSources => 'Mga pinagmulan ng data';
+
+ @override
+ String get dataSourceTremNet => '探索智慧科技有限公司 — TREM-Net';
+
+ @override
+ String get dataSourceCwa => '交通部中央氣象署 (CWA)';
+
+ @override
+ String get dataSourceJma => '気象庁 (JMA)';
+
+ @override
+ String get dataSourceNcdr => '國家災害防救科技中心 (NCDR)';
+
+ @override
+ String get dataSourceEcmwf =>
+ 'European Centre for Medium-Range Weather Forecasts (ECMWF)';
+
+ @override
+ String get dataSourceNoaaGfs =>
+ 'National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)';
+
+ @override
+ String get dataSourceGovernmentOpenData => '政府資料開放平臺';
+
+ @override
+ String get dataSourceOpenStreetMap => '© OpenStreetMap contributors';
+
+ @override
+ String get dataSourceNasaMoon =>
+ 'National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)';
+
+ @override
+ String mapOsmDetailsHint(int enabled, int total) {
+ return '$enabled sa $total na layer ang naka-enable';
+ }
+
+ @override
+ String get mapOsmSurface => 'Ibabaw';
+
+ @override
+ String get mapOsmParks => 'Mga parke';
+
+ @override
+ String get mapOsmLandUse => 'Paggamit ng lupa';
+
+ @override
+ String get mapOsmAirportAreas => 'Mga lugar ng paliparan';
+
+ @override
+ String get mapOsmWater => 'Tubig';
+
+ @override
+ String get mapOsmRivers => 'Mga ilog';
+
+ @override
+ String get mapOsmBoundaries => 'Mga hangganan';
+
+ @override
+ String get mapOsmBuildings => 'Mga gusali';
+
+ @override
+ String get mapOsmRoads => 'Mga kalsada';
+
+ @override
+ String get mapOsmRoadNames => 'Pangalan ng kalsada';
+
+ @override
+ String get mapOsmWaterNames => 'Pangalan ng tubig';
+
+ @override
+ String get mapOsmPeaks => 'Mga taluktok';
+
+ @override
+ String get mapOsmAirportNames => 'Pangalan ng paliparan';
+
+ @override
+ String get mapOsmPlaceNames => 'Pangalan ng lugar';
+
+ @override
+ String get mapOsmPoi => 'Mga lugar ng interes';
+
+ @override
+ String get mapOsmHouseNumbers => 'Mga numero ng bahay';
+
+ @override
+ String get mapOsmRestoreAll => 'Ibalik lahat';
+
+ @override
+ String get mapOsmSectionNatural => 'Mga likas na anyo';
+
+ @override
+ String get mapOsmSectionRoadsAndBuildings => 'Mga kalsada at gusali';
+
+ @override
+ String get mapOsmSectionLabelsAndPlaces => 'Mga label at lugar';
+
@override
String get mapTownLabels => 'Mga pangalan ng bayan';
@@ -2331,10 +2446,10 @@ class AppLocalizationsFil extends AppLocalizations {
String get notifySetFailed => 'Hindi ma-save ang setting. Pakisubukan muli.';
@override
- String get meshtasticDisconnect => 'Disconnect';
+ String get meshtasticDisconnect => 'I-disconnect';
@override
- String get meshtasticUndecoded => 'Not decrypted';
+ String get meshtasticUndecoded => 'Hindi nade-decrypt';
@override
String get notifyAnnouncement => 'Mga Anunsyo';
@@ -2371,7 +2486,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get moonSectionAppearance => 'Anyo';
@override
- String get moonSectionRiseSet => 'Pagsikat at paglubog';
+ String get moonSectionRiseSet => 'Paosmkat at paglubog';
@override
String get moonSectionUpcoming => 'Susunod';
@@ -2389,7 +2504,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get moonApparentSize => 'Lapad sa langit';
@override
- String get moonRise => 'Pagsikat ng buwan';
+ String get moonRise => 'Paosmkat ng buwan';
@override
String get moonSet => 'Paglubog ng buwan';
@@ -2422,7 +2537,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get sunSectionTerms => 'Solar terms';
@override
- String get sunRise => 'Pagsikat ng araw';
+ String get sunRise => 'Paosmkat ng araw';
@override
String get sunSet => 'Paglubog ng araw';
@@ -2584,7 +2699,7 @@ class AppLocalizationsFil extends AppLocalizations {
String get solarTermMajorCold => 'Major Cold';
@override
- String get solarTermStartOfSpring => 'Simula ng Tagsibol';
+ String get solarTermStartOfSpring => 'Simula ng Taosmbol';
@override
String get solarTermRainWater => 'Rain Water';
@@ -2872,6 +2987,55 @@ class AppLocalizationsFil extends AppLocalizations {
return 'Tinanggihan ang “$what” at hindi na magtatanong ang sistema. I-on ito sa Settings.';
}
+ @override
+ String get permissionGuideNotification =>
+ 'Buksan ang System Settings upang payagan ang mga notipikasyon.';
+
+ @override
+ String get permissionGuideForegroundLocation =>
+ 'Buksan ang System Settings upang payagan ang tumpak na lokasyon.';
+
+ @override
+ String permissionGuideBackgroundLocation(Object option) {
+ return 'Sa “$option”, piliin ang “Payagan sa lahat ng oras”.';
+ }
+
+ @override
+ String get permissionGuideBackgroundExecution =>
+ 'Payagan ang background execution sa System Settings upang hindi i-pause ang mga notipikasyon.';
+
+ @override
+ String get permissionGuideUnusedPause =>
+ 'Kung minarkahan ang app na “hindi ginagamit”, piliin ang “Payagan” sa System Settings.';
+
+ @override
+ String get permissionGuideUnusedFreeSpace =>
+ 'Kung na-pause ang app dahil sa storage, i-clear ang cache at buksan muli.';
+
+ @override
+ String get permissionGuideUnusedRevoke =>
+ 'Kung binawi ang mga pahintulot ng app, ibigay muli sa System Settings.';
+
+ @override
+ String get permissionGuideUnusedPlayProtect =>
+ 'Kung i-pause ng Play Protect ang app, tingnan ang katayuan nito sa Google Play.';
+
+ @override
+ String permissionGuideVendorPower(Object vendor) {
+ return 'Sa mga setting ng pagtitipid ng kuryente ng “$vendor”, itakda ang app na ito sa “Walang limitasyon”.';
+ }
+
+ @override
+ String get permissionStillRequired =>
+ 'Kailangan pa rin — buksan ang Settings para paganahin.';
+
+ @override
+ String get permissionVerifyManually =>
+ 'Mangyaring i-verify nang manu-mano na naka-enable ang pahintulot na ito sa System Settings.';
+
+ @override
+ String get permissionBackgroundLocationOption => '“Payagan sa lahat ng oras”';
+
@override
String get displayTextSize => 'Laki ng teksto';
@@ -3021,6 +3185,16 @@ class AppLocalizationsFil extends AppLocalizations {
String get moreDumpDiagnosticsHint =>
'Iuupload at kokopyahin ang link para ilakip sa ulat';
+ @override
+ String get dumpIncludeSensitive => 'Isama ang eksaktong lokasyon';
+
+ @override
+ String get dumpIncludeSensitiveHint =>
+ 'Isinasama ang mga coordinate mula sa log at lokasyon sa background; kapag hindi pinili, papalitan ng null';
+
+ @override
+ String get dumpUpload => 'I-upload';
+
@override
String get dumpUploaded => 'Na-upload';
diff --git a/lib/l10n/gen/app_localizations_id.dart b/lib/l10n/gen/app_localizations_id.dart
index b39ec23f3..0ae6f08ce 100644
--- a/lib/l10n/gen/app_localizations_id.dart
+++ b/lib/l10n/gen/app_localizations_id.dart
@@ -56,7 +56,7 @@ class AppLocalizationsId extends AppLocalizations {
String get restroomTypeMale => 'Toilet pria';
@override
- String get meshtasticLastReceived => 'Last received';
+ String get meshtasticLastReceived => 'Terakhir diterima';
@override
String get reportDetailSortByCounty => 'Urutkan menurut wilayah';
@@ -87,7 +87,7 @@ class AppLocalizationsId extends AppLocalizations {
String get homeRainTrendScattered => 'Kemungkinan hujan ringan';
@override
- String get meshtasticUptime => 'Uptime';
+ String get meshtasticUptime => 'Waktu aktif';
@override
String get weatherRankingTempExtremes => 'Ekstrem suhu';
@@ -99,7 +99,7 @@ class AppLocalizationsId extends AppLocalizations {
String get mapTerrainReliefHint => 'Tampilkan relief terrain di peta dasar';
@override
- String get meshtasticEmptyMessage => '(empty message)';
+ String get meshtasticEmptyMessage => '(pesan kosong)';
@override
String get moreSectionRegion => 'Wilayah';
@@ -111,7 +111,7 @@ class AppLocalizationsId extends AppLocalizations {
String get aedHoursSaturday => 'Jam Sabtu';
@override
- String get moonPhaseNew => 'New moon';
+ String get moonPhaseNew => 'Bulan baru';
@override
String get notifySectionEew => 'Peringatan dini gempa';
@@ -126,7 +126,7 @@ class AppLocalizationsId extends AppLocalizations {
String get mapTownLabelsHint => 'Tampilkan nama kecamatan saat diperbesar';
@override
- String get commonCancel => 'Cancel';
+ String get commonCancel => 'Batal';
@override
String get notifyOptTsunamiWarning => 'Hanya peringatan tsunami';
@@ -166,7 +166,7 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get mapLayerStyleJmaTooltip =>
- 'Grayscale base, tinted below −40 °C to highlight cloud-top height';
+ 'Basis grayscale, diwarnai di bawah −40 °C untuk menyorot tinggi puncak awan';
@override
String get mapLayerRain => 'Curah hujan';
@@ -220,7 +220,7 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get meshtasticExcludeMqttSubtitle =>
- 'Nodes bridged over the internet, not heard by radio';
+ 'Node yang terhubung lewat internet, tidak terdengar lewat radio';
@override
String get reportFilterIntensityInfoTitle => 'Skala intensitas baru & lama';
@@ -232,14 +232,14 @@ class AppLocalizationsId extends AppLocalizations {
String get radarOverlayMenuTooltip => 'Opsi lapisan radar';
@override
- String get meshtasticNodes => 'Nodes';
+ String get meshtasticNodes => 'Node';
@override
- String get meshtasticSend => 'Send';
+ String get meshtasticSend => 'Kirim';
@override
String get typhoonOverlayStormL7Tooltip =>
- 'Level-7 wind field + average circle (purple)';
+ 'Medan angin level 7 + lingkaran rata-rata (ungu)';
@override
String get aedType => 'Jenis';
@@ -300,7 +300,7 @@ class AppLocalizationsId extends AppLocalizations {
String get reportFilterSortMagnitude => 'Magnitudo';
@override
- String get meshtasticSilent => 'Silent';
+ String get meshtasticSilent => 'Senyap';
@override
String get mapLayerCategoryEarthquake => 'Gempa';
@@ -334,7 +334,7 @@ class AppLocalizationsId extends AppLocalizations {
String get notifyOptTsunamiAll => 'Imbauan dan peringatan tsunami';
@override
- String get meshtasticLayerOptions => 'Node options';
+ String get meshtasticLayerOptions => 'Opsi node';
@override
String get onboardingAgreeContinue => 'Setuju dan lanjutkan';
@@ -343,7 +343,7 @@ class AppLocalizationsId extends AppLocalizations {
String get commonRetry => 'Coba lagi';
@override
- String get meshtasticNodeId => 'Node ID';
+ String get meshtasticNodeId => 'ID Node';
@override
String reportDetailNumbered(String number) {
@@ -351,7 +351,7 @@ class AppLocalizationsId extends AppLocalizations {
}
@override
- String get typhoonOverlayStormBandSubtitle => 'With average circle';
+ String get typhoonOverlayStormBandSubtitle => 'Dengan lingkaran rata-rata';
@override
String get disasterMapOverlayRestroomTooltip => 'Tampilkan toilet umum';
@@ -379,13 +379,13 @@ class AppLocalizationsId extends AppLocalizations {
String get sponsorRestore => 'Pulihkan pembelian';
@override
- String get meshtasticChannelWorking => 'Setting up the DPIP channel…';
+ String get meshtasticChannelWorking => 'Menyiapkan kanal DPIP…';
@override
- String get meshtasticRegionSwitch => 'Switch to TW';
+ String get meshtasticRegionSwitch => 'Beralih ke TW';
@override
- String get meshtasticTraffic => 'Traffic';
+ String get meshtasticTraffic => 'Lalu lintas';
@override
String get mapLayerStyleBdTooltip =>
@@ -399,10 +399,10 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentNight =>
- 'Night = transparent, the basemap shows';
+ 'Malam = transparan, peta dasar terlihat';
@override
- String get meshtasticScanning => 'Scanning…';
+ String get meshtasticScanning => 'Memindai…';
@override
String regionSelectFull(int max) {
@@ -474,7 +474,7 @@ class AppLocalizationsId extends AppLocalizations {
String get navMore => 'Lainnya';
@override
- String get meshtasticDpipChannel => 'DPIP channel';
+ String get meshtasticDpipChannel => 'Kanal DPIP';
@override
String get disasterMapOverlaySectionLayers => 'Lapisan';
@@ -486,7 +486,7 @@ class AppLocalizationsId extends AppLocalizations {
String get typhoonLabelNe => 'NE';
@override
- String get meshtasticCopied => 'Message copied';
+ String get meshtasticCopied => 'Pesan disalin';
@override
String get reportListEmpty => 'Tidak ada laporan gempa';
@@ -498,19 +498,20 @@ class AppLocalizationsId extends AppLocalizations {
String get mapLayerSatelliteTruecolor => 'Himawari True Color';
@override
- String get typhoonOverlaySectionExtra => 'Overlays';
+ String get typhoonOverlaySectionExtra => 'Lapisan tambahan';
@override
String get eewSWave => 'Gelombang S';
@override
- String get meshtasticBusyTitle => 'Another app is using this radio';
+ String get meshtasticBusyTitle =>
+ 'Aplikasi lain sedang menggunakan radio ini';
@override
String get restroomCategoryCultural => 'Tempat budaya';
@override
- String get typhoonLabelWind => 'Max. sustained wind near centre';
+ String get typhoonLabelWind => 'Angin bertahan maks. dekat pusat';
@override
String get radarGlobalOutlineHint => 'Bingkai luar setiap negara';
@@ -522,7 +523,7 @@ class AppLocalizationsId extends AppLocalizations {
String get typhoonLegendCircle15 => 'Lingkar angin kencang';
@override
- String get dataSectionAstronomy => 'Astronomy';
+ String get dataSectionAstronomy => 'Astronomi';
@override
String get homeRainTrendLightSustained =>
@@ -532,10 +533,10 @@ class AppLocalizationsId extends AppLocalizations {
String get commonError => 'Terjadi kesalahan';
@override
- String get moonPhaseWaningCrescent => 'Waning crescent';
+ String get moonPhaseWaningCrescent => 'Bulan sabit memudar';
@override
- String get meshtasticPower => 'Power';
+ String get meshtasticPower => 'Daya';
@override
String get mapTimelineNow => 'Sekarang';
@@ -563,7 +564,7 @@ class AppLocalizationsId extends AppLocalizations {
String get notifyTitle => 'Notifikasi';
@override
- String get meshtasticTxPower => 'TX power';
+ String get meshtasticTxPower => 'Daya TX';
@override
String get restroomCategoryLabel => 'Kategori';
@@ -576,7 +577,7 @@ class AppLocalizationsId extends AppLocalizations {
'DPIP berdedikasi menyediakan informasi mitigasi bencana secara real-time, tanpa iklan atau model bisnis lainnya. Dukungan Anda membantu kami menjaga server tetap berjalan dan terus mengembangkan aplikasi.';
@override
- String get typhoonLabelStormAvg => 'Avg. radius of Beaufort 10 winds';
+ String get typhoonLabelStormAvg => 'Jari-jari rata-rata angin Beaufort 10';
@override
String get restroomCategoryCommercial => 'Tempat komersial';
@@ -610,10 +611,11 @@ class AppLocalizationsId extends AppLocalizations {
String get restroomTypeUnspecified => 'Tidak ditentukan';
@override
- String get typhoonOverlayProbabilityHint => 'Hides the forecast cone';
+ String get typhoonOverlayProbabilityHint =>
+ 'Menyembunyikan kerucut prakiraan';
@override
- String get mapLayerSatelliteGlobalOutline => 'Country border';
+ String get mapLayerSatelliteGlobalOutline => 'Batas negara';
@override
String get mapNavTemperature => 'Suhu';
@@ -648,7 +650,7 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get typhoonOverlayWeatherRadarTooltip =>
- 'Radar echo closest to the typhoon bulletin time';
+ 'Gema radar terdekat dengan waktu buletin topan';
@override
String get onboardingPermLocationDesc =>
@@ -661,13 +663,13 @@ class AppLocalizationsId extends AppLocalizations {
String get homeActiveEventsEmpty => 'Tidak ada peristiwa aktif';
@override
- String get typhoonLabelPosition => 'Centre location';
+ String get typhoonLabelPosition => 'Lokasi pusat';
@override
String get weatherRankingBy => 'Urut';
@override
- String get typhoonIntensityMild => 'Mild typhoon';
+ String get typhoonIntensityMild => 'Topan lemah';
@override
String get windForecastGlobalOutlineHint => 'Bingkai luar setiap negara';
@@ -685,7 +687,7 @@ class AppLocalizationsId extends AppLocalizations {
String get restroomCategoryReligious => 'Tempat ibadah';
@override
- String get meshtasticRole => 'Role';
+ String get meshtasticRole => 'Peran';
@override
String get mapLayerSatelliteCloudCloudy => 'Cloudy';
@@ -697,7 +699,7 @@ class AppLocalizationsId extends AppLocalizations {
String get meshtasticJumpToLatest => 'Ke yang terbaru';
@override
- String get meshtasticNoMessages => 'No messages yet';
+ String get meshtasticNoMessages => 'Belum ada pesan';
@override
String get onboardingPermNotifyDesc =>
@@ -707,7 +709,7 @@ class AppLocalizationsId extends AppLocalizations {
String get radarTownOutline => 'Batas kecamatan';
@override
- String get mapLayerStyleSection => 'Colour style';
+ String get mapLayerStyleSection => 'Gaya warna';
@override
String get disasterMapOverlayMenuTooltip => 'Lapisan peta bencana';
@@ -716,14 +718,14 @@ class AppLocalizationsId extends AppLocalizations {
String get moreGooglePlay => 'Google Play';
@override
- String get meshtasticOnline => 'Heard recently';
+ String get meshtasticOnline => 'Baru terdengar';
@override
String get typhoonLabelSw => 'SW';
@override
String typhoonForecastLead(String hours) {
- return 'Forecast +$hours h';
+ return 'Prakiraan +$hours jam';
}
@override
@@ -731,7 +733,7 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentClear =>
- 'Clear sky = transparent, the basemap shows';
+ 'Langit cerah = transparan, peta dasar terlihat';
@override
String get mapOverlaySectionReference => 'Lapisan referensi';
@@ -765,7 +767,7 @@ class AppLocalizationsId extends AppLocalizations {
String get eewArrived => 'Tiba';
@override
- String get meshtasticNoDevices => 'No Meshtastic devices found';
+ String get meshtasticNoDevices => 'Tidak menemukan perangkat Meshtastic';
@override
String get mapLayerCategoryLife => 'Kehidupan sehari-hari';
@@ -774,10 +776,10 @@ class AppLocalizationsId extends AppLocalizations {
String get reportFilterSortIntensity => 'Intensitas';
@override
- String get meshtasticStateDisconnected => 'Disconnected';
+ String get meshtasticStateDisconnected => 'Terputus';
@override
- String get typhoonIntensityIntense => 'Intense typhoon';
+ String get typhoonIntensityIntense => 'Topan kuat';
@override
String get mapLayerOrderTitle => 'Urutkan lapisan';
@@ -786,7 +788,7 @@ class AppLocalizationsId extends AppLocalizations {
String get dpmYes => 'Ya';
@override
- String get meshtasticNoHistory => 'Not enough history yet';
+ String get meshtasticNoHistory => 'Riwayat belum cukup';
@override
String get reportDetailLocalIntensityUnavailable =>
@@ -808,16 +810,16 @@ class AppLocalizationsId extends AppLocalizations {
String get notifyAdvisory => 'Imbauan cuaca';
@override
- String get reportFilterReset => 'Reset';
+ String get reportFilterReset => 'Atur ulang';
@override
String get mapLayerSatelliteMndwi => 'Himawari MNDWI';
@override
- String get typhoonOverlaySectionStorm => 'Storm wind';
+ String get typhoonOverlaySectionStorm => 'Angin badai';
@override
- String get moonPhaseFull => 'Full moon';
+ String get moonPhaseFull => 'Bulan purnama';
@override
String meshtasticBinaryPayload(String size) {
@@ -825,14 +827,14 @@ class AppLocalizationsId extends AppLocalizations {
}
@override
- String get moonPhaseWaningGibbous => 'Waning gibbous';
+ String get moonPhaseWaningGibbous => 'Bulan cembung memudar';
@override
String get reportFilterIntensityInfoModernTitle => 'Baru (sejak 2020)';
@override
String typhoonDataTime(String time) {
- return 'Data time\n$time';
+ return 'Waktu data';
}
@override
@@ -842,7 +844,7 @@ class AppLocalizationsId extends AppLocalizations {
String get moreSectionAbout => 'Tentang';
@override
- String get meshtasticSelectDevice => 'Select a radio';
+ String get meshtasticSelectDevice => 'Pilih radio';
@override
String get onboardingIntroBody =>
@@ -855,19 +857,19 @@ class AppLocalizationsId extends AppLocalizations {
String get reportDetailImage => 'Gambar laporan';
@override
- String get meshtasticStateConfiguring => 'Configuring…';
+ String get meshtasticStateConfiguring => 'Mengonfigurasi…';
@override
- String get typhoonLabelGaleAvg => 'Avg. radius of Beaufort 7 winds';
+ String get typhoonLabelGaleAvg => 'Jari-jari rata-rata angin Beaufort 7';
@override
String get onboardingPermNotify => 'Notifikasi';
@override
- String get meshtasticClearMessages => 'Clear messages';
+ String get meshtasticClearMessages => 'Hapus pesan';
@override
- String get meshtasticNotifyMessages => 'Notify on new messages';
+ String get meshtasticNotifyMessages => 'Beri tahu saat pesan baru';
@override
String get defaultMapLayerSettings => 'Lapisan peta bawaan';
@@ -945,7 +947,7 @@ class AppLocalizationsId extends AppLocalizations {
String get mapTimelineFuture => 'Mendatang';
@override
- String get typhoonLegendCircleAvg => 'Average circle';
+ String get typhoonLegendCircleAvg => 'Lingkaran rata-rata';
@override
String reportFilterDepthKm(String depth) {
@@ -964,7 +966,7 @@ class AppLocalizationsId extends AppLocalizations {
}
@override
- String get typhoonLabelGust => 'Peak gust';
+ String get typhoonLabelGust => 'Embusan puncak';
@override
String get mapAppGoogleMaps => 'Google Maps';
@@ -982,7 +984,7 @@ class AppLocalizationsId extends AppLocalizations {
String get skyTimeGolden => 'Jam emas';
@override
- String get moonAge => 'Age';
+ String get moonAge => 'Umur bulan';
@override
String get meshtasticRadioSettings => 'LoRa';
@@ -997,7 +999,7 @@ class AppLocalizationsId extends AppLocalizations {
String get mapLayers => 'Lapisan';
@override
- String get meshtasticHardware => 'Hardware';
+ String get meshtasticHardware => 'Perangkat keras';
@override
String get languageSettings => 'Bahasa';
@@ -1011,7 +1013,7 @@ class AppLocalizationsId extends AppLocalizations {
}
@override
- String get typhoonOverlayWeatherHint => 'Aligned to bulletin time';
+ String get typhoonOverlayWeatherHint => 'Diselaraskan dengan waktu buletin';
@override
String get skyTimeDawn => 'Fajar';
@@ -1020,7 +1022,7 @@ class AppLocalizationsId extends AppLocalizations {
String get skyTimeAfternoon => 'Sore';
@override
- String get meshtasticLastHeard => 'Last heard';
+ String get meshtasticLastHeard => 'Terakhir terdengar';
@override
String get typhoonWarningTitle => 'Peringatan topan';
@@ -1071,10 +1073,10 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get typhoonOverlayStormL10Tooltip =>
- 'Level-10 wind field + average circle (yellow)';
+ 'Medan angin level 10 + lingkaran rata-rata (kuning)';
@override
- String get moonPhaseWaxingGibbous => 'Waxing gibbous';
+ String get moonPhaseWaxingGibbous => 'Bulan cembung membesar';
@override
String get reportDetailTitle => 'Laporan Gempa';
@@ -1088,10 +1090,10 @@ class AppLocalizationsId extends AppLocalizations {
}
@override
- String get meshtasticNoNodes => 'No nodes heard yet';
+ String get meshtasticNoNodes => 'Belum ada node yang terdengar';
@override
- String get meshtasticViaMqtt => 'Via MQTT (internet)';
+ String get meshtasticViaMqtt => 'Lewat MQTT (internet)';
@override
String get radarCountyOutline => 'Batas kabupaten/kota';
@@ -1109,11 +1111,11 @@ class AppLocalizationsId extends AppLocalizations {
String get changelogCurrentVersion => 'Saat ini';
@override
- String get typhoonLabelPressure => 'Central pressure';
+ String get typhoonLabelPressure => 'Tekanan pusat';
@override
String get typhoonOverlayForecastCalloutsTooltip =>
- 'Show forecast-point detail cards when zoomed in';
+ 'Tampilkan kartu detail titik prakiraan saat diperbesar';
@override
String get aedOpenRemark => 'Catatan jam buka';
@@ -1123,7 +1125,7 @@ class AppLocalizationsId extends AppLocalizations {
'Agar DPIP dapat memperingatkan Anda saat bencana terjadi, harap berikan izin berikut. Anda dapat mengubahnya kapan saja di pengaturan sistem.';
@override
- String get typhoonOverlaySectionWeather => 'Weather underlay';
+ String get typhoonOverlaySectionWeather => 'Lapisan bawah cuaca';
@override
String get notifyOptWeatherLocal => 'Hanya lokasi saat ini';
@@ -1132,7 +1134,7 @@ class AppLocalizationsId extends AppLocalizations {
String get mapNavRain => 'Hujan';
@override
- String get moonDays => 'days';
+ String get moonDays => 'hari';
@override
String mapLegendUnit(String unit) {
@@ -1152,10 +1154,10 @@ class AppLocalizationsId extends AppLocalizations {
String get mapLayerSatelliteB01 => 'Himawari Blue (B01)';
@override
- String get meshtasticExternalPower => 'External power';
+ String get meshtasticExternalPower => 'Daya eksternal';
@override
- String get moonPhaseLastQuarter => 'Last quarter';
+ String get moonPhaseLastQuarter => 'Kuartal akhir';
@override
String get reportFilterOrderAsc => 'Menaik';
@@ -1182,19 +1184,19 @@ class AppLocalizationsId extends AppLocalizations {
String get restroomGradeExcellent => 'Sangat baik';
@override
- String get meshtasticLastSent => 'Last sent';
+ String get meshtasticLastSent => 'Terakhir dikirim';
@override
- String get meshtasticName => 'Name';
+ String get meshtasticName => 'Nama';
@override
- String get meshtasticScan => 'Scan';
+ String get meshtasticScan => 'Pindai';
@override
String get mapLayerCategoryForecast => 'Prakiraan numerik';
@override
- String get meshtasticChannelFailed => 'Couldn\'t set up the DPIP channel';
+ String get meshtasticChannelFailed => 'Gagal menyiapkan kanal DPIP';
@override
String get themeSystem => 'Sistem';
@@ -1214,7 +1216,7 @@ class AppLocalizationsId extends AppLocalizations {
String get weatherPrecipitation => 'Curah hujan';
@override
- String get moonNextFullMoon => 'Next full moon';
+ String get moonNextFullMoon => 'Purnama berikutnya';
@override
String get dpmSheetEmpty => 'Ketuk penanda di peta untuk detail';
@@ -1243,7 +1245,7 @@ class AppLocalizationsId extends AppLocalizations {
String get typhoonLabelNw => 'NW';
@override
- String get moonPhaseWaxingCrescent => 'Waxing crescent';
+ String get moonPhaseWaxingCrescent => 'Bulan sabit membesar';
@override
String get restroomCategoryLeisure => 'Tempat rekreasi';
@@ -1255,23 +1257,23 @@ class AppLocalizationsId extends AppLocalizations {
String get aedCategory => 'Kategori';
@override
- String get meshtasticChannels => 'Channels';
+ String get meshtasticChannels => 'Kanal';
@override
String get monitorWaiting => 'Menunggu data…';
@override
- String get typhoonOverlayForecastCallouts => 'Forecast tooltips';
+ String get typhoonOverlayForecastCallouts => 'Tooltip prakiraan';
@override
String get reportDetailEpicenter => 'Koordinat episentrum';
@override
- String get meshtasticVoltage => 'Voltage';
+ String get meshtasticVoltage => 'Tegangan';
@override
String get mapLayerMeshtasticSubtitle =>
- 'LoRa mesh nodes heard by your radio';
+ 'Node mesh LoRa yang terdengar radio Anda';
@override
String get mapLayerWind => 'Angin';
@@ -1309,7 +1311,7 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentZero =>
- 'Zero difference = transparent (no signal)';
+ 'Selisih nol = transparan (tanpa sinyal)';
@override
String get shelterIndoorLabel => 'Penampungan dalam ruangan';
@@ -1321,7 +1323,7 @@ class AppLocalizationsId extends AppLocalizations {
String get reportFilterSortTime => 'Waktu';
@override
- String get mapLayerSatelliteCloudProbablyClear => 'Probably clear';
+ String get mapLayerSatelliteCloudProbablyClear => 'Mungkin cerah';
@override
String get weatherModeThunderstorm => 'Badai petir';
@@ -1333,7 +1335,7 @@ class AppLocalizationsId extends AppLocalizations {
String get reportFilterIntensityInfoLegacyTitle => 'Lama (sebelum 2020)';
@override
- String get typhoonLabelSpeed => 'Past movement speed';
+ String get typhoonLabelSpeed => 'Kecepatan gerak';
@override
String mapAppOpenFailed(String app) {
@@ -1341,10 +1343,10 @@ class AppLocalizationsId extends AppLocalizations {
}
@override
- String get mapLayerSatelliteRgbComposite => 'RGB composite (JMA recipe)';
+ String get mapLayerSatelliteRgbComposite => 'Komposit RGB (resep JMA)';
@override
- String get meshtasticReceived => 'Received';
+ String get meshtasticReceived => 'Diterima';
@override
String get weatherRankingExtremeLow => 'Minimum hari ini';
@@ -1353,7 +1355,7 @@ class AppLocalizationsId extends AppLocalizations {
String get mapLayerSatelliteB10 => 'Himawari Lower Water Vapour (B10)';
@override
- String get mapLayerSatelliteCloudProbablyCloudy => 'Probably cloudy';
+ String get mapLayerSatelliteCloudProbablyCloudy => 'Mungkin berawan';
@override
String get mapLayerSatelliteTransparentNoWater =>
@@ -1363,10 +1365,10 @@ class AppLocalizationsId extends AppLocalizations {
String get shelterCategoryLabel => 'Jenis bencana';
@override
- String get meshtasticStateConnecting => 'Connecting…';
+ String get meshtasticStateConnecting => 'Menghubungkan…';
@override
- String get moonTitle => 'Moon';
+ String get moonTitle => 'Bulan';
@override
String get weatherRankingGust => 'Hembusan';
@@ -1381,7 +1383,7 @@ class AppLocalizationsId extends AppLocalizations {
String get notifySectionWeather => 'Cuaca';
@override
- String get meshtasticPreset => 'Modem preset';
+ String get meshtasticPreset => 'Preset modem';
@override
String get dataSectionSeismic => 'Seismik';
@@ -1408,13 +1410,13 @@ class AppLocalizationsId extends AppLocalizations {
String get regionCurrent => 'Lokasi saat ini';
@override
- String get meshtasticNotConnected => 'Not connected to a radio';
+ String get meshtasticNotConnected => 'Belum terhubung ke radio';
@override
String get weatherModeSnow => 'Salju';
@override
- String get mapLayerMeshtastic => 'Meshtastic nodes';
+ String get mapLayerMeshtastic => 'Node Meshtastic';
@override
String get moreDeveloper => 'Info debug';
@@ -1423,7 +1425,7 @@ class AppLocalizationsId extends AppLocalizations {
String get mapLayerSatelliteB14 => 'Himawari Longwave Infrared (B14)';
@override
- String get meshtasticChannelUse => 'Channel use';
+ String get meshtasticChannelUse => 'Penggunaan kanal';
@override
String get mapNavLightning => 'Petir';
@@ -1447,7 +1449,7 @@ class AppLocalizationsId extends AppLocalizations {
String get dpmOpenInMaps => 'Buka di peta';
@override
- String get meshtasticNotifyNodes => 'Notify on new nodes';
+ String get meshtasticNotifyNodes => 'Beri tahu saat node baru';
@override
String get onboardingPermCriticalDesc =>
@@ -1455,10 +1457,10 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentWarm =>
- 'Clear sky (warm end) = transparent, the basemap shows';
+ 'Langit cerah (ujung hangat) = transparan, peta dasar terlihat';
@override
- String get meshtasticSent => 'Sent';
+ String get meshtasticSent => 'Terkirim';
@override
String get homeForecastTitle => 'Prakiraan 24 jam';
@@ -1468,7 +1470,7 @@ class AppLocalizationsId extends AppLocalizations {
@override
String meshtasticExcludeMqttHidden(int count) {
- return '$count hidden';
+ return '$count disembunyikan';
}
@override
@@ -1484,13 +1486,13 @@ class AppLocalizationsId extends AppLocalizations {
String get reportListToday => 'Hari ini';
@override
- String get meshtasticTapNode => 'Tap a node for details';
+ String get meshtasticTapNode => 'Ketuk node untuk detail';
@override
String get commonLoading => 'Memuat…';
@override
- String get typhoonIntensityModerate => 'Moderate typhoon';
+ String get typhoonIntensityModerate => 'Topan sedang';
@override
String get mapLayerSatelliteAsh => 'Himawari Ash';
@@ -1502,14 +1504,14 @@ class AppLocalizationsId extends AppLocalizations {
String get mapLayerCategorySatellite => 'Satelit';
@override
- String get meshtasticChannelReady => 'DPIP channel ready';
+ String get meshtasticChannelReady => 'Kanal DPIP siap';
@override
String get mapLayerSatelliteNightmicrophysics =>
'Himawari Night Microphysics';
@override
- String get typhoonIntensityTd => 'Tropical depression';
+ String get typhoonIntensityTd => 'Depresi tropis';
@override
String get reportFilterDate => 'Tanggal';
@@ -1584,7 +1586,7 @@ class AppLocalizationsId extends AppLocalizations {
String get mapLayerSatelliteBtdSo2 => 'Himawari SO₂ / Cloud Phase';
@override
- String get meshtasticStateError => 'Error';
+ String get meshtasticStateError => 'Kesalahan';
@override
String get weatherModeOvercast => 'Mendung';
@@ -1594,7 +1596,7 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get typhoonOverlayWarningTooltip =>
- 'Highlight counties under a typhoon warning';
+ 'Sorot kabupaten dalam peringatan topan';
@override
String get reportFilterDatePick => 'Pilih tanggal';
@@ -1609,7 +1611,7 @@ class AppLocalizationsId extends AppLocalizations {
String get shelterOutdoorLabel => 'Penampungan luar ruangan';
@override
- String get meshtasticStateConnected => 'Connected';
+ String get meshtasticStateConnected => 'Terhubung';
@override
String get mapNavRadar => 'Radar';
@@ -1628,7 +1630,7 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get typhoonOverlayWeatherNoneTooltip =>
- 'No radar or infrared underlay';
+ 'Tanpa lapisan bawah radar atau inframerah';
@override
String get radarCountyOutlineHint => 'Digambar di atas gema';
@@ -1640,13 +1642,13 @@ class AppLocalizationsId extends AppLocalizations {
String get homeRainTrendTitle => 'Hujan 1 jam ke depan';
@override
- String get moonPhaseFirstQuarter => 'First quarter';
+ String get moonPhaseFirstQuarter => 'Kuartal pertama';
@override
String get mapLayerCategoryTyphoon => 'Topan';
@override
- String get meshtasticUtilization => 'Airtime (24h)';
+ String get meshtasticUtilization => 'Waktu udara (24 jam)';
@override
String get restroomTypeMixed => 'Toilet campuran';
@@ -1664,7 +1666,7 @@ class AppLocalizationsId extends AppLocalizations {
String get mapLayerSatelliteBtdWvirw => 'Himawari Overshooting Top';
@override
- String get meshtasticReadingAge => 'Reading taken';
+ String get meshtasticReadingAge => 'Waktu pengukuran';
@override
String get mapAppCallFailed =>
@@ -1686,7 +1688,7 @@ class AppLocalizationsId extends AppLocalizations {
String get reportDetailLocalFelt => 'Gempa Dirasakan Lokal';
@override
- String get meshtasticDevice => 'Device';
+ String get meshtasticDevice => 'Perangkat';
@override
String get onboardingGrant => 'Berikan';
@@ -1735,7 +1737,7 @@ class AppLocalizationsId extends AppLocalizations {
'Tidak ada laporan yang cocok dengan filter';
@override
- String get meshtasticExcludeMqtt => 'Hide MQTT nodes';
+ String get meshtasticExcludeMqtt => 'Sembunyikan node MQTT';
@override
String get mapNavTyphoon => 'Topan';
@@ -1773,13 +1775,13 @@ class AppLocalizationsId extends AppLocalizations {
String get navHome => 'Beranda';
@override
- String get meshtasticRegionLabel => 'Region';
+ String get meshtasticRegionLabel => 'Wilayah';
@override
String get mapLayerSatelliteCloudtop => 'Himawari Cloud Top Temperature';
@override
- String get moonTimelineCaption => 'Phase';
+ String get moonTimelineCaption => 'Fase';
@override
String get openSourceLicenses => 'Lisensi sumber terbuka';
@@ -1799,7 +1801,7 @@ class AppLocalizationsId extends AppLocalizations {
String get radarScanRange => 'Tampilkan jangkauan pindai';
@override
- String get meshtasticHopLimit => 'Hop limit';
+ String get meshtasticHopLimit => 'Batas lompatan';
@override
String get weatherRankingExtremeHigh => 'Maksimum hari ini';
@@ -1814,7 +1816,7 @@ class AppLocalizationsId extends AppLocalizations {
String get mapLayerSatelliteNaturalcolor => 'Himawari Natural Color';
@override
- String get meshtasticAirtime => 'Air time (TX)';
+ String get meshtasticAirtime => 'Waktu udara (TX)';
@override
String shelterCapacityValue(int n) {
@@ -1827,7 +1829,7 @@ class AppLocalizationsId extends AppLocalizations {
}
@override
- String get meshtasticSendHint => 'Message to broadcast';
+ String get meshtasticSendHint => 'Pesan untuk disiarkan';
@override
String monitorDelay(String value) {
@@ -1841,7 +1843,7 @@ class AppLocalizationsId extends AppLocalizations {
String get mapLayerSatelliteB08 => 'Himawari Upper Water Vapour (B08)';
@override
- String get meshtasticReconnecting => 'Reconnecting…';
+ String get meshtasticReconnecting => 'Menghubungkan ulang…';
@override
String get radarTownOutlineSubtitle =>
@@ -1849,14 +1851,14 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get typhoonOverlayWeatherSatelliteTooltip =>
- 'Infrared closest to the typhoon bulletin time';
+ 'Inframerah terdekat dengan waktu buletin topan';
@override
String get radarScanRangeHint => 'Di luar kotak berarti tak terpantau';
@override
String typhoonPickerTd(String no) {
- return 'Tropical depression TD $no';
+ return 'Depresi tropis TD $no';
}
@override
@@ -1879,7 +1881,7 @@ class AppLocalizationsId extends AppLocalizations {
'Layanan lokasi mati — peringatan lokal tidak dapat menargetkan wilayah Anda.';
@override
- String get mapLayerStyleTooltip => 'Colour style';
+ String get mapLayerStyleTooltip => 'Gaya warna';
@override
String lightningLegendCg(int minutes) {
@@ -2020,7 +2022,7 @@ class AppLocalizationsId extends AppLocalizations {
String get endpointServiceWind => 'Wind';
@override
- String get endpointServiceDpm => 'Disaster points';
+ String get endpointServiceDpm => 'Titik bencana';
@override
String get endpointServiceWeather => 'Weather';
@@ -2038,7 +2040,7 @@ class AppLocalizationsId extends AppLocalizations {
String get endpointServiceReport => 'EQ reports';
@override
- String get endpointServiceTremStation => 'Tremor station';
+ String get endpointServiceTremStation => 'Stasiun getaran';
@override
String get endpointServiceEvent => 'Events';
@@ -2074,17 +2076,17 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get meshtasticBusyBody =>
- 'Disconnect it in the other Meshtastic app first. Two apps on one radio take each other\'s messages, so some will go missing.';
+ 'Putuskan koneksinya dulu di aplikasi Meshtastic lain. Dua aplikasi pada satu radio saling mengambil pesan, jadi sebagian akan hilang.';
@override
String get meshtasticChannelNoSlot =>
- 'No free channel slot — free one on the radio';
+ 'Tidak ada slot kanal kosong — kosongkan satu di radio';
@override
String get restroomCategoryTransport => 'Transportasi';
@override
- String get meshtasticBattery => 'Battery';
+ String get meshtasticBattery => 'Baterai';
@override
String get meshtasticDistance => 'Jarak';
@@ -2096,14 +2098,14 @@ class AppLocalizationsId extends AppLocalizations {
String get meshtasticBatteryTrend => 'Tren baterai';
@override
- String get typhoonOverlayMenuTooltip => 'Typhoon overlay options';
+ String get typhoonOverlayMenuTooltip => 'Opsi lapisan topan';
@override
String get mapLayerSatelliteBtdOzone => 'Himawari Tropopause';
@override
String meshtasticRegionMismatch(String region) {
- return 'Radio region is $region — DPIP needs TW';
+ return 'Wilayah radio adalah $region — DPIP membutuhkan TW';
}
@override
@@ -2133,10 +2135,16 @@ class AppLocalizationsId extends AppLocalizations {
String get moreVersionStable => 'Versi resmi';
@override
- String get moreVersionNotes => 'Versi saat ini';
+ String get moreVersionNotes => 'Pembaruan ini';
@override
- String get releaseHighlightsTitle => 'Yang berubah';
+ String get moreVersionNotesHighlightsSubtitle =>
+ 'Apa yang berubah di versi ini';
+
+ @override
+ String releaseHighlightsTitle(Object train) {
+ return '$train rangkuman';
+ }
@override
String get releaseHighlightsTabNormal => 'Untuk pengguna';
@@ -2189,7 +2197,7 @@ class AppLocalizationsId extends AppLocalizations {
String get weatherModeAuto => 'Otomatis';
@override
- String get typhoonLabelProbCircle => '70% probability circle';
+ String get typhoonLabelProbCircle => 'Lingkaran probabilitas 70%';
@override
String get notifyOptAll => 'Terima semua';
@@ -2201,14 +2209,14 @@ class AppLocalizationsId extends AppLocalizations {
String get mapLayerSatelliteB07 => 'Himawari Shortwave Infrared (B07)';
@override
- String get typhoonLabelDirection => 'Past movement direction';
+ String get typhoonLabelDirection => 'Arah gerak';
@override
String get regionManageTitle => 'Wilayah tersimpan';
@override
String get regionSaveNote =>
- 'Notifikasi dikirim berdasarkan lokasi GPS Anda. Menyimpan wilayah sering dipakai tidak mengubah tempat pengiriman peringatan — wilayah sering dipakai hanya agar status tiap wilayah terlihat cepat di beranda. Izinkan akses lokasi, jika tidak notifikasi tidak berfungsi.';
+ 'Notifikasi dikirim berdasarkan lokasi GPS Anda. Menyimpan wilayah sering dipakai tidak mengubah tempat pengiriman peringatan — wilayah sering dipakai hanya agar status tiap wilayah terlihat cepat di beranda. Izinkan akses lokasi, jika tidak notifikasi tidak berfunosm.';
@override
String get typhoonLegendCone => 'Kerucut prakiraan';
@@ -2220,13 +2228,13 @@ class AppLocalizationsId extends AppLocalizations {
String get onboardingPermsTitle => 'Izin';
@override
- String get mapLayerStyleJma => 'Cloud-top enhancement (JMA)';
+ String get mapLayerStyleJma => 'Peningkatan puncak awan (JMA)';
@override
String get rainInterval10m => '10 mnt';
@override
- String get meshtasticConnectAnyway => 'Connect anyway';
+ String get meshtasticConnectAnyway => 'Tetap hubungkan';
@override
String reportListDayCount(int count) {
@@ -2238,7 +2246,7 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentReflectance =>
- 'Low reflectance / night = transparent, the basemap shows';
+ 'Reflektansi rendah / malam = transparan, peta dasar terlihat';
@override
String chartHourLabel(int hour) {
@@ -2250,7 +2258,7 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get typhoonOverlayProbabilityTooltip =>
- 'Show strike probability (hides the forecast cone)';
+ 'Tampilkan probabilitas hantaman (menyembunyikan kerucut prakiraan)';
@override
String get mapLayerSatelliteNdwi => 'Himawari NDWI';
@@ -2271,7 +2279,7 @@ class AppLocalizationsId extends AppLocalizations {
String get mapLayerCategoryRadar => 'Radar';
@override
- String get meshtasticShortName => 'Short name';
+ String get meshtasticShortName => 'Nama pendek';
@override
String get mapLayerSatelliteAirmass => 'Himawari Airmass';
@@ -2298,7 +2306,7 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get meshtasticRegionConfirm =>
- 'Switch this radio to the TW region? It restarts and disconnects for a moment, and every other channel on it moves too.';
+ 'Beralihkan radio ini ke wilayah TW? Radio akan mulai ulang dan terputus sesaat, dan semua kanal lain ikut pindah.';
@override
String get dataEarthquakeSubtitle => 'Laporan gempa';
@@ -2315,6 +2323,114 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get onboardingTermsTitle => 'Ketentuan Layanan';
+ @override
+ String get mapOsmOverlay => 'Peta detail';
+
+ @override
+ String get mapOsmOverlayHint =>
+ 'Tampilkan jalan, bangunan, dan nama tempat yang lebih lengkap';
+
+ @override
+ String get mapOsmDetails => 'Detail lapisan';
+
+ @override
+ String get moreDataSources => 'Sumber data';
+
+ @override
+ String get dataSourceTremNet => '探索智慧科技有限公司 — TREM-Net';
+
+ @override
+ String get dataSourceCwa => '交通部中央氣象署 (CWA)';
+
+ @override
+ String get dataSourceJma => '気象庁 (JMA)';
+
+ @override
+ String get dataSourceNcdr => '國家災害防救科技中心 (NCDR)';
+
+ @override
+ String get dataSourceEcmwf =>
+ 'European Centre for Medium-Range Weather Forecasts (ECMWF)';
+
+ @override
+ String get dataSourceNoaaGfs =>
+ 'National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)';
+
+ @override
+ String get dataSourceGovernmentOpenData => '政府資料開放平臺';
+
+ @override
+ String get dataSourceOpenStreetMap => '© OpenStreetMap contributors';
+
+ @override
+ String get dataSourceNasaMoon =>
+ 'National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)';
+
+ @override
+ String mapOsmDetailsHint(int enabled, int total) {
+ return '$enabled dari $total lapisan aktif';
+ }
+
+ @override
+ String get mapOsmSurface => 'Permukaan';
+
+ @override
+ String get mapOsmParks => 'Taman';
+
+ @override
+ String get mapOsmLandUse => 'Penggunaan lahan';
+
+ @override
+ String get mapOsmAirportAreas => 'Area bandara';
+
+ @override
+ String get mapOsmWater => 'Perairan';
+
+ @override
+ String get mapOsmRivers => 'Sungai';
+
+ @override
+ String get mapOsmBoundaries => 'Batas';
+
+ @override
+ String get mapOsmBuildings => 'Bangunan';
+
+ @override
+ String get mapOsmRoads => 'Jalan';
+
+ @override
+ String get mapOsmRoadNames => 'Nama jalan';
+
+ @override
+ String get mapOsmWaterNames => 'Nama perairan';
+
+ @override
+ String get mapOsmPeaks => 'Puncak';
+
+ @override
+ String get mapOsmAirportNames => 'Nama bandara';
+
+ @override
+ String get mapOsmPlaceNames => 'Nama tempat';
+
+ @override
+ String get mapOsmPoi => 'Tempat menarik';
+
+ @override
+ String get mapOsmHouseNumbers => 'Nomor rumah';
+
+ @override
+ String get mapOsmRestoreAll => 'Pulihkan semua';
+
+ @override
+ String get mapOsmSectionNatural => 'Fitur alam';
+
+ @override
+ String get mapOsmSectionRoadsAndBuildings => 'Jalan & bangunan';
+
+ @override
+ String get mapOsmSectionLabelsAndPlaces => 'Label & tempat';
+
@override
String get mapTownLabels => 'Nama kecamatan';
@@ -2323,10 +2439,10 @@ class AppLocalizationsId extends AppLocalizations {
'Tidak dapat menyimpan pengaturan. Silakan coba lagi.';
@override
- String get meshtasticDisconnect => 'Disconnect';
+ String get meshtasticDisconnect => 'Putuskan';
@override
- String get meshtasticUndecoded => 'Not decrypted';
+ String get meshtasticUndecoded => 'Belum didekripsi';
@override
String get notifyAnnouncement => 'Pengumuman';
@@ -2441,7 +2557,7 @@ class AppLocalizationsId extends AppLocalizations {
String get sunGoldenHourEvening => 'Golden hour sore';
@override
- String get sunBlueHour => 'Blue hour';
+ String get sunBlueHour => 'Jam biru';
@override
String get sunEquationOfTime => 'Persamaan waktu';
@@ -2865,6 +2981,55 @@ class AppLocalizationsId extends AppLocalizations {
return '“$what” ditolak dan sistem tidak akan bertanya lagi. Aktifkan di Pengaturan.';
}
+ @override
+ String get permissionGuideNotification =>
+ 'Buka Pengaturan Sistem untuk mengizinkan notifikasi.';
+
+ @override
+ String get permissionGuideForegroundLocation =>
+ 'Buka Pengaturan Sistem untuk mengizinkan lokasi presisi.';
+
+ @override
+ String permissionGuideBackgroundLocation(Object option) {
+ return 'Di “$option”, pilih “Izinkan sepanjang waktu”.';
+ }
+
+ @override
+ String get permissionGuideBackgroundExecution =>
+ 'Izinkan eksekusi latar belakang di Pengaturan Sistem agar notifikasi tidak dijeda.';
+
+ @override
+ String get permissionGuideUnusedPause =>
+ 'Jika aplikasi ditandai “tidak digunakan”, pilih “Izinkan” di Pengaturan Sistem.';
+
+ @override
+ String get permissionGuideUnusedFreeSpace =>
+ 'Jika aplikasi dijeda karena penyimpanan, bersihkan cache dan buka kembali.';
+
+ @override
+ String get permissionGuideUnusedRevoke =>
+ 'Jika izin aplikasi dicabut, berikan lagi di Pengaturan Sistem.';
+
+ @override
+ String get permissionGuideUnusedPlayProtect =>
+ 'Jika Play Protect menjeda aplikasi, periksa statusnya di Google Play.';
+
+ @override
+ String permissionGuideVendorPower(Object vendor) {
+ return 'Di pengaturan hemat daya “$vendor”, atur aplikasi ini ke “Tanpa batas”.';
+ }
+
+ @override
+ String get permissionStillRequired =>
+ 'Masih diperlukan — buka Pengaturan untuk mengaktifkannya.';
+
+ @override
+ String get permissionVerifyManually =>
+ 'Periksa secara manual bahwa izin ini diaktifkan di Pengaturan Sistem.';
+
+ @override
+ String get permissionBackgroundLocationOption => '“Izinkan sepanjang waktu”';
+
@override
String get displayTextSize => 'Ukuran teks';
@@ -3014,6 +3179,16 @@ class AppLocalizationsId extends AppLocalizations {
String get moreDumpDiagnosticsHint =>
'Mengunggah lalu menyalin tautan untuk dilampirkan ke laporan';
+ @override
+ String get dumpIncludeSensitive => 'Sertakan lokasi presisi';
+
+ @override
+ String get dumpIncludeSensitiveHint =>
+ 'Menyertakan koordinat dari log dan lokasi latar belakang; jika tidak dipilih, diganti dengan null';
+
+ @override
+ String get dumpUpload => 'Unggah';
+
@override
String get dumpUploaded => 'Terunggah';
diff --git a/lib/l10n/gen/app_localizations_ja.dart b/lib/l10n/gen/app_localizations_ja.dart
index dcb9a9556..6eddc7366 100644
--- a/lib/l10n/gen/app_localizations_ja.dart
+++ b/lib/l10n/gen/app_localizations_ja.dart
@@ -55,7 +55,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get restroomTypeMale => '男性用トイレ';
@override
- String get meshtasticLastReceived => 'Last received';
+ String get meshtasticLastReceived => '最終受信';
@override
String get reportDetailSortByCounty => '地域順に並べ替え';
@@ -86,7 +86,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get homeRainTrendScattered => 'にわか雨の可能性があります';
@override
- String get meshtasticUptime => 'Uptime';
+ String get meshtasticUptime => '稼働時間';
@override
String get weatherRankingTempExtremes => '気温極値';
@@ -98,7 +98,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get mapTerrainReliefHint => 'ベースマップに地形の陰影を表示';
@override
- String get meshtasticEmptyMessage => '(empty message)';
+ String get meshtasticEmptyMessage => '(空メッセージ)';
@override
String get moreSectionRegion => '地域';
@@ -110,7 +110,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get aedHoursSaturday => '土曜の開館時間';
@override
- String get moonPhaseNew => 'New moon';
+ String get moonPhaseNew => '新月';
@override
String get notifySectionEew => '緊急地震速報';
@@ -125,7 +125,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get mapTownLabelsHint => '拡大すると郷鎮名を表示';
@override
- String get commonCancel => 'Cancel';
+ String get commonCancel => 'キャンセル';
@override
String get notifyOptTsunamiWarning => '津波警報のみ';
@@ -218,7 +218,7 @@ class AppLocalizationsJa extends AppLocalizations {
@override
String get meshtasticExcludeMqttSubtitle =>
- 'Nodes bridged over the internet, not heard by radio';
+ 'インターネット経由で橋渡しされたノード(無線では受信していません)';
@override
String get reportFilterIntensityInfoTitle => '震度の新制と旧制';
@@ -230,10 +230,10 @@ class AppLocalizationsJa extends AppLocalizations {
String get radarOverlayMenuTooltip => 'レーダーレイヤー設定';
@override
- String get meshtasticNodes => 'Nodes';
+ String get meshtasticNodes => 'ノード';
@override
- String get meshtasticSend => 'Send';
+ String get meshtasticSend => '送信';
@override
String get typhoonOverlayStormL7Tooltip => '強風域 + 平均円(紫)';
@@ -288,7 +288,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get skyTimeDusk => '薄暮';
@override
- String get meshtasticFirmware => 'Firmware';
+ String get meshtasticFirmware => 'ファームウェア';
@override
String get reportFilterDateEndNote => '終了日:当日 24:00(台北時間)';
@@ -297,7 +297,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get reportFilterSortMagnitude => '規模';
@override
- String get meshtasticSilent => 'Silent';
+ String get meshtasticSilent => 'サイレント';
@override
String get mapLayerCategoryEarthquake => '地震';
@@ -331,7 +331,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get notifyOptTsunamiAll => '津波情報・津波警報';
@override
- String get meshtasticLayerOptions => 'Node options';
+ String get meshtasticLayerOptions => 'ノードオプション';
@override
String get onboardingAgreeContinue => '同意して続行';
@@ -340,7 +340,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get commonRetry => '再試行';
@override
- String get meshtasticNodeId => 'Node ID';
+ String get meshtasticNodeId => 'ノード ID';
@override
String reportDetailNumbered(String number) {
@@ -375,13 +375,13 @@ class AppLocalizationsJa extends AppLocalizations {
String get sponsorRestore => '購入を復元';
@override
- String get meshtasticChannelWorking => 'Setting up the DPIP channel…';
+ String get meshtasticChannelWorking => 'DPIP チャンネルを設定中…';
@override
- String get meshtasticRegionSwitch => 'Switch to TW';
+ String get meshtasticRegionSwitch => 'TW 地域に切り替え';
@override
- String get meshtasticTraffic => 'Traffic';
+ String get meshtasticTraffic => 'トラフィック';
@override
String get mapLayerStyleBdTooltip => 'Dvorak BD カーブ——熱帯低気圧の強度解析に使う階段グレースケール';
@@ -396,7 +396,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get mapLayerSatelliteTransparentNight => '夜間 = 透明、地図が透ける';
@override
- String get meshtasticScanning => 'Scanning…';
+ String get meshtasticScanning => 'スキャン中…';
@override
String regionSelectFull(int max) {
@@ -468,7 +468,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get navMore => 'その他';
@override
- String get meshtasticDpipChannel => 'DPIP channel';
+ String get meshtasticDpipChannel => 'DPIP チャンネル';
@override
String get disasterMapOverlaySectionLayers => 'レイヤー';
@@ -480,7 +480,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get typhoonLabelNe => '北東';
@override
- String get meshtasticCopied => 'Message copied';
+ String get meshtasticCopied => 'メッセージをコピーしました';
@override
String get reportListEmpty => '地震報告はありません';
@@ -498,7 +498,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get eewSWave => 'S波';
@override
- String get meshtasticBusyTitle => 'Another app is using this radio';
+ String get meshtasticBusyTitle => '別のアプリがこの無線機を使用中です';
@override
String get restroomCategoryCultural => '文化・娯楽施設';
@@ -516,7 +516,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get typhoonLegendCircle15 => '強風域(30kt)';
@override
- String get dataSectionAstronomy => 'Astronomy';
+ String get dataSectionAstronomy => '天文';
@override
String get homeRainTrendLightSustained => '今後1時間は小雨が続きます';
@@ -525,10 +525,10 @@ class AppLocalizationsJa extends AppLocalizations {
String get commonError => '問題が発生しました';
@override
- String get moonPhaseWaningCrescent => 'Waning crescent';
+ String get moonPhaseWaningCrescent => '下弦の月';
@override
- String get meshtasticPower => 'Power';
+ String get meshtasticPower => '電源';
@override
String get mapTimelineNow => '現在';
@@ -556,7 +556,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get notifyTitle => '通知';
@override
- String get meshtasticTxPower => 'TX power';
+ String get meshtasticTxPower => 'TX 出力';
@override
String get restroomCategoryLabel => '区分';
@@ -676,7 +676,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get restroomCategoryReligious => '宗教・礼拝施設';
@override
- String get meshtasticRole => 'Role';
+ String get meshtasticRole => 'ロール';
@override
String get mapLayerSatelliteCloudCloudy => '雲';
@@ -688,7 +688,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get meshtasticJumpToLatest => '最新へ移動';
@override
- String get meshtasticNoMessages => 'No messages yet';
+ String get meshtasticNoMessages => 'まだメッセージがありません';
@override
String get onboardingPermNotifyDesc => '地震、天気、災害の発生時に、警報をすぐお届けします。';
@@ -706,7 +706,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get moreGooglePlay => 'Google Play';
@override
- String get meshtasticOnline => 'Heard recently';
+ String get meshtasticOnline => '最近受信あり';
@override
String get typhoonLabelSw => '南西';
@@ -752,7 +752,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get eewArrived => '到達';
@override
- String get meshtasticNoDevices => 'No Meshtastic devices found';
+ String get meshtasticNoDevices => 'Meshtastic デバイスが見つかりません';
@override
String get mapLayerCategoryLife => '生活';
@@ -761,7 +761,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get reportFilterSortIntensity => '震度';
@override
- String get meshtasticStateDisconnected => 'Disconnected';
+ String get meshtasticStateDisconnected => '切断済み';
@override
String get typhoonIntensityIntense => '強い台風';
@@ -773,7 +773,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get dpmYes => 'はい';
@override
- String get meshtasticNoHistory => 'Not enough history yet';
+ String get meshtasticNoHistory => '履歴がまだ足りません';
@override
String get reportDetailLocalIntensityUnavailable => '震度情報なし';
@@ -803,7 +803,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get typhoonOverlaySectionStorm => '暴風域';
@override
- String get moonPhaseFull => 'Full moon';
+ String get moonPhaseFull => '満月';
@override
String meshtasticBinaryPayload(String size) {
@@ -811,7 +811,7 @@ class AppLocalizationsJa extends AppLocalizations {
}
@override
- String get moonPhaseWaningGibbous => 'Waning gibbous';
+ String get moonPhaseWaningGibbous => '下弦の月(虧)';
@override
String get reportFilterIntensityInfoModernTitle => '新制(2020 年以降)';
@@ -828,7 +828,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get moreSectionAbout => '情報';
@override
- String get meshtasticSelectDevice => 'Select a radio';
+ String get meshtasticSelectDevice => '無線機を選択';
@override
String get onboardingIntroBody =>
@@ -841,7 +841,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get reportDetailImage => '地震レポート画像';
@override
- String get meshtasticStateConfiguring => 'Configuring…';
+ String get meshtasticStateConfiguring => '設定中…';
@override
String get typhoonLabelGaleAvg => '強風域の平均半径';
@@ -850,10 +850,10 @@ class AppLocalizationsJa extends AppLocalizations {
String get onboardingPermNotify => '通知';
@override
- String get meshtasticClearMessages => 'Clear messages';
+ String get meshtasticClearMessages => 'メッセージを消去';
@override
- String get meshtasticNotifyMessages => 'Notify on new messages';
+ String get meshtasticNotifyMessages => '新しいメッセージで通知';
@override
String get defaultMapLayerSettings => '地図の初期レイヤー';
@@ -964,7 +964,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get skyTimeGolden => 'ゴールデンアワー';
@override
- String get moonAge => 'Age';
+ String get moonAge => '月齢';
@override
String get meshtasticRadioSettings => 'LoRa';
@@ -979,7 +979,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get mapLayers => 'レイヤー';
@override
- String get meshtasticHardware => 'Hardware';
+ String get meshtasticHardware => 'ハードウェア';
@override
String get languageSettings => '言語設定';
@@ -1002,7 +1002,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get skyTimeAfternoon => '午後';
@override
- String get meshtasticLastHeard => 'Last heard';
+ String get meshtasticLastHeard => '最終受信';
@override
String get typhoonWarningTitle => '台風警報';
@@ -1055,7 +1055,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get typhoonOverlayStormL10Tooltip => '暴風域 + 平均円(黄)';
@override
- String get moonPhaseWaxingGibbous => 'Waxing gibbous';
+ String get moonPhaseWaxingGibbous => '上弦の月(盈)';
@override
String get reportDetailTitle => '地震レポート';
@@ -1069,10 +1069,10 @@ class AppLocalizationsJa extends AppLocalizations {
}
@override
- String get meshtasticNoNodes => 'No nodes heard yet';
+ String get meshtasticNoNodes => 'まだノードを検出していません';
@override
- String get meshtasticViaMqtt => 'Via MQTT (internet)';
+ String get meshtasticViaMqtt => 'MQTT 経由(インターネット)';
@override
String get radarCountyOutline => '県市境界';
@@ -1112,7 +1112,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get mapNavRain => '雨量';
@override
- String get moonDays => 'days';
+ String get moonDays => '日';
@override
String mapLegendUnit(String unit) {
@@ -1123,7 +1123,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get weatherModeClear => '晴れ';
@override
- String get meshtasticRadio => 'Radio';
+ String get meshtasticRadio => '無線機';
@override
String get commonEmpty => '表示する項目がありません';
@@ -1132,10 +1132,10 @@ class AppLocalizationsJa extends AppLocalizations {
String get mapLayerSatelliteB01 => 'ひまわり 可視青(B01)';
@override
- String get meshtasticExternalPower => 'External power';
+ String get meshtasticExternalPower => '外部電源';
@override
- String get moonPhaseLastQuarter => 'Last quarter';
+ String get moonPhaseLastQuarter => '下弦';
@override
String get reportFilterOrderAsc => '昇順';
@@ -1162,19 +1162,19 @@ class AppLocalizationsJa extends AppLocalizations {
String get restroomGradeExcellent => '最上級';
@override
- String get meshtasticLastSent => 'Last sent';
+ String get meshtasticLastSent => '最終送信';
@override
- String get meshtasticName => 'Name';
+ String get meshtasticName => '名前';
@override
- String get meshtasticScan => 'Scan';
+ String get meshtasticScan => 'スキャン';
@override
String get mapLayerCategoryForecast => '数値予報';
@override
- String get meshtasticChannelFailed => 'Couldn\'t set up the DPIP channel';
+ String get meshtasticChannelFailed => 'DPIP チャンネルの設定に失敗しました';
@override
String get themeSystem => 'システム';
@@ -1194,7 +1194,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get weatherPrecipitation => '降水量';
@override
- String get moonNextFullMoon => 'Next full moon';
+ String get moonNextFullMoon => '次の満月';
@override
String get dpmSheetEmpty => '地図上のマーカーをタップして詳細を表示';
@@ -1223,7 +1223,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get typhoonLabelNw => '北西';
@override
- String get moonPhaseWaxingCrescent => 'Waxing crescent';
+ String get moonPhaseWaxingCrescent => '上弦';
@override
String get restroomCategoryLeisure => 'レジャー・娯楽施設';
@@ -1235,7 +1235,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get aedCategory => '分類';
@override
- String get meshtasticChannels => 'Channels';
+ String get meshtasticChannels => 'チャンネル';
@override
String get monitorWaiting => 'データ待機中…';
@@ -1247,11 +1247,10 @@ class AppLocalizationsJa extends AppLocalizations {
String get reportDetailEpicenter => '震央座標';
@override
- String get meshtasticVoltage => 'Voltage';
+ String get meshtasticVoltage => '電圧';
@override
- String get mapLayerMeshtasticSubtitle =>
- 'LoRa mesh nodes heard by your radio';
+ String get mapLayerMeshtasticSubtitle => '無線機で受信した LoRa メッシュノード';
@override
String get mapLayerWind => '風向';
@@ -1323,7 +1322,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get mapLayerSatelliteRgbComposite => 'RGB 合成(JMA レシピ)';
@override
- String get meshtasticReceived => 'Received';
+ String get meshtasticReceived => '受信';
@override
String get weatherRankingExtremeLow => '今日の最低';
@@ -1341,10 +1340,10 @@ class AppLocalizationsJa extends AppLocalizations {
String get shelterCategoryLabel => '対象災害';
@override
- String get meshtasticStateConnecting => 'Connecting…';
+ String get meshtasticStateConnecting => '接続中…';
@override
- String get moonTitle => 'Moon';
+ String get moonTitle => '月';
@override
String get weatherRankingGust => '突風';
@@ -1359,7 +1358,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get notifySectionWeather => '天気';
@override
- String get meshtasticPreset => 'Modem preset';
+ String get meshtasticPreset => 'モデムプリセット';
@override
String get dataSectionSeismic => '地震';
@@ -1386,13 +1385,13 @@ class AppLocalizationsJa extends AppLocalizations {
String get regionCurrent => '現在地';
@override
- String get meshtasticNotConnected => 'Not connected to a radio';
+ String get meshtasticNotConnected => '無線機に接続されていません';
@override
String get weatherModeSnow => '雪';
@override
- String get mapLayerMeshtastic => 'Meshtastic nodes';
+ String get mapLayerMeshtastic => 'Meshtastic ノード';
@override
String get moreDeveloper => 'デバッグ情報';
@@ -1401,7 +1400,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get mapLayerSatelliteB14 => 'ひまわり 長波長赤外線(B14)';
@override
- String get meshtasticChannelUse => 'Channel use';
+ String get meshtasticChannelUse => 'チャンネル使用率';
@override
String get mapNavLightning => '稲妻';
@@ -1425,7 +1424,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get dpmOpenInMaps => '地図アプリで開く';
@override
- String get meshtasticNotifyNodes => 'Notify on new nodes';
+ String get meshtasticNotifyNodes => '新しいノードで通知';
@override
String get onboardingPermCriticalDesc =>
@@ -1435,7 +1434,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get mapLayerSatelliteTransparentWarm => '晴れ(暖域) = 透明、地図が透ける';
@override
- String get meshtasticSent => 'Sent';
+ String get meshtasticSent => '送信済み';
@override
String get homeForecastTitle => '24時間予報';
@@ -1445,7 +1444,7 @@ class AppLocalizationsJa extends AppLocalizations {
@override
String meshtasticExcludeMqttHidden(int count) {
- return '$count hidden';
+ return '$count 件を非表示';
}
@override
@@ -1461,7 +1460,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get reportListToday => '今日';
@override
- String get meshtasticTapNode => 'Tap a node for details';
+ String get meshtasticTapNode => 'ノードをタップして詳細を表示';
@override
String get commonLoading => '読み込み中…';
@@ -1479,7 +1478,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get mapLayerCategorySatellite => '衛星';
@override
- String get meshtasticChannelReady => 'DPIP channel ready';
+ String get meshtasticChannelReady => 'DPIP チャンネルの準備ができました';
@override
String get mapLayerSatelliteNightmicrophysics => 'ひまわり 夜間微物理';
@@ -1558,7 +1557,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get mapLayerSatelliteBtdSo2 => 'ひまわり 二酸化硫黄/雲相';
@override
- String get meshtasticStateError => 'Error';
+ String get meshtasticStateError => 'エラー';
@override
String get weatherModeOvercast => '本曇り';
@@ -1582,7 +1581,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get shelterOutdoorLabel => '屋外収容';
@override
- String get meshtasticStateConnected => 'Connected';
+ String get meshtasticStateConnected => '接続済み';
@override
String get mapNavRadar => 'レーダー';
@@ -1611,13 +1610,13 @@ class AppLocalizationsJa extends AppLocalizations {
String get homeRainTrendTitle => '今後1時間の雨';
@override
- String get moonPhaseFirstQuarter => 'First quarter';
+ String get moonPhaseFirstQuarter => '上弦の月';
@override
String get mapLayerCategoryTyphoon => '台風';
@override
- String get meshtasticUtilization => 'Airtime (24h)';
+ String get meshtasticUtilization => 'エアタイム(24h)';
@override
String get restroomTypeMixed => '男女共用トイレ';
@@ -1635,7 +1634,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get mapLayerSatelliteBtdWvirw => 'ひまわり オーバーシューティングトップ';
@override
- String get meshtasticReadingAge => 'Reading taken';
+ String get meshtasticReadingAge => '計測時刻';
@override
String get mapAppCallFailed => 'この端末では通話できません';
@@ -1656,7 +1655,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get reportDetailLocalFelt => '局地的な有感地震';
@override
- String get meshtasticDevice => 'Device';
+ String get meshtasticDevice => 'デバイス';
@override
String get onboardingGrant => '許可';
@@ -1704,7 +1703,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get reportListEmptyFiltered => '条件に一致する地震報告はありません';
@override
- String get meshtasticExcludeMqtt => 'Hide MQTT nodes';
+ String get meshtasticExcludeMqtt => 'MQTT ノードを隠す';
@override
String get mapNavTyphoon => '台風';
@@ -1742,13 +1741,13 @@ class AppLocalizationsJa extends AppLocalizations {
String get navHome => 'ホーム';
@override
- String get meshtasticRegionLabel => 'Region';
+ String get meshtasticRegionLabel => '地域';
@override
String get mapLayerSatelliteCloudtop => 'ひまわり 雲頂温度';
@override
- String get moonTimelineCaption => 'Phase';
+ String get moonTimelineCaption => '月相';
@override
String get openSourceLicenses => 'オープンソースライセンス';
@@ -1768,7 +1767,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get radarScanRange => '走査範囲を表示';
@override
- String get meshtasticHopLimit => 'Hop limit';
+ String get meshtasticHopLimit => 'ホップ数上限';
@override
String get weatherRankingExtremeHigh => '今日の最高';
@@ -1783,7 +1782,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get mapLayerSatelliteNaturalcolor => 'ひまわり ナチュラルカラー';
@override
- String get meshtasticAirtime => 'Air time (TX)';
+ String get meshtasticAirtime => 'エアタイム(TX)';
@override
String shelterCapacityValue(int n) {
@@ -1796,7 +1795,7 @@ class AppLocalizationsJa extends AppLocalizations {
}
@override
- String get meshtasticSendHint => 'Message to broadcast';
+ String get meshtasticSendHint => '送信するメッセージ';
@override
String monitorDelay(String value) {
@@ -1810,7 +1809,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get mapLayerSatelliteB08 => 'ひまわり 上層水蒸気(B08)';
@override
- String get meshtasticReconnecting => 'Reconnecting…';
+ String get meshtasticReconnecting => '再接続中…';
@override
String get radarTownOutlineSubtitle => 'レーダーエコーの下でも市町村境界が見えるようにします。';
@@ -1971,49 +1970,49 @@ class AppLocalizationsJa extends AppLocalizations {
String get endpointServiceRts => 'RTS';
@override
- String get endpointServiceRadar => 'Radar';
+ String get endpointServiceRadar => 'レーダー';
@override
- String get endpointServiceSatellite => 'Satellite';
+ String get endpointServiceSatellite => '衛星画像';
@override
String get endpointServiceQpesums => 'QPE';
@override
- String get endpointServiceWind => 'Wind';
+ String get endpointServiceWind => '風';
@override
- String get endpointServiceDpm => 'Disaster points';
+ String get endpointServiceDpm => '災害地点';
@override
- String get endpointServiceWeather => 'Weather';
+ String get endpointServiceWeather => '天気';
@override
- String get endpointServiceRain => 'Rain';
+ String get endpointServiceRain => '雨';
@override
- String get endpointServiceLightning => 'Lightning';
+ String get endpointServiceLightning => '雷';
@override
- String get endpointServiceTyphoon => 'Typhoon';
+ String get endpointServiceTyphoon => '台風';
@override
- String get endpointServiceReport => 'EQ reports';
+ String get endpointServiceReport => '地震報告';
@override
- String get endpointServiceTremStation => 'Tremor station';
+ String get endpointServiceTremStation => '震度計';
@override
- String get endpointServiceEvent => 'Events';
+ String get endpointServiceEvent => 'イベント';
@override
- String get endpointServiceLocation => 'Location';
+ String get endpointServiceLocation => '位置情報';
@override
- String get endpointServiceNotify => 'Notifications';
+ String get endpointServiceNotify => '通知';
@override
- String get endpointServiceOther => 'Other';
+ String get endpointServiceOther => 'その他';
@override
String get feedConnecting => '接続中…';
@@ -2036,17 +2035,16 @@ class AppLocalizationsJa extends AppLocalizations {
@override
String get meshtasticBusyBody =>
- 'Disconnect it in the other Meshtastic app first. Two apps on one radio take each other\'s messages, so some will go missing.';
+ '先に別の Meshtastic アプリで無線機を切断してください。1 台の無線機を 2 つのアプリで使うと互いのメッセージを奪い合い、一部が失われます。';
@override
- String get meshtasticChannelNoSlot =>
- 'No free channel slot — free one on the radio';
+ String get meshtasticChannelNoSlot => '空きチャンネルがありません — 無線機で1つ空けてください';
@override
String get restroomCategoryTransport => '交通';
@override
- String get meshtasticBattery => 'Battery';
+ String get meshtasticBattery => 'バッテリー';
@override
String get meshtasticDistance => '距離';
@@ -2065,7 +2063,7 @@ class AppLocalizationsJa extends AppLocalizations {
@override
String meshtasticRegionMismatch(String region) {
- return 'Radio region is $region — DPIP needs TW';
+ return '無線機の地域は $region です — DPIP は TW が必要です';
}
@override
@@ -2095,10 +2093,15 @@ class AppLocalizationsJa extends AppLocalizations {
String get moreVersionStable => '正式版';
@override
- String get moreVersionNotes => '現在のバージョン';
+ String get moreVersionNotes => '今回の更新';
@override
- String get releaseHighlightsTitle => '今回の更新';
+ String get moreVersionNotesHighlightsSubtitle => 'このバージョンでの変更点';
+
+ @override
+ String releaseHighlightsTitle(Object train) {
+ return '$train まとめ';
+ }
@override
String get releaseHighlightsTabNormal => '変更点';
@@ -2187,7 +2190,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get rainInterval10m => '10分';
@override
- String get meshtasticConnectAnyway => 'Connect anyway';
+ String get meshtasticConnectAnyway => '接続する';
@override
String reportListDayCount(int count) {
@@ -2230,7 +2233,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get mapLayerCategoryRadar => 'レーダー';
@override
- String get meshtasticShortName => 'Short name';
+ String get meshtasticShortName => '短縮名';
@override
String get mapLayerSatelliteAirmass => 'ひまわり エアマス';
@@ -2257,7 +2260,7 @@ class AppLocalizationsJa extends AppLocalizations {
@override
String get meshtasticRegionConfirm =>
- 'Switch this radio to the TW region? It restarts and disconnects for a moment, and every other channel on it moves too.';
+ 'この無線機を TW 地域に切り替えますか?再起動して一時的に切断され、他のチャンネルも移動します。';
@override
String get dataEarthquakeSubtitle => '地震報告';
@@ -2274,6 +2277,113 @@ class AppLocalizationsJa extends AppLocalizations {
@override
String get onboardingTermsTitle => 'サービス利用規約';
+ @override
+ String get mapOsmOverlay => '詳細地図';
+
+ @override
+ String get mapOsmOverlayHint => '道路、建物、地名をより詳しく表示';
+
+ @override
+ String get mapOsmDetails => '詳細地図のレイヤー';
+
+ @override
+ String get moreDataSources => 'データ提供元';
+
+ @override
+ String get dataSourceTremNet => '探索智慧科技有限公司 — TREM-Net';
+
+ @override
+ String get dataSourceCwa => '交通部中央氣象署 (CWA)';
+
+ @override
+ String get dataSourceJma => '気象庁 (JMA)';
+
+ @override
+ String get dataSourceNcdr => '國家災害防救科技中心 (NCDR)';
+
+ @override
+ String get dataSourceEcmwf =>
+ 'European Centre for Medium-Range Weather Forecasts (ECMWF)';
+
+ @override
+ String get dataSourceNoaaGfs =>
+ 'National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)';
+
+ @override
+ String get dataSourceGovernmentOpenData => '政府資料開放平臺';
+
+ @override
+ String get dataSourceOpenStreetMap => '© OpenStreetMap contributors';
+
+ @override
+ String get dataSourceNasaMoon =>
+ 'National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)';
+
+ @override
+ String mapOsmDetailsHint(int enabled, int total) {
+ return '$enabled / $total レイヤーを有効化';
+ }
+
+ @override
+ String get mapOsmSurface => '地表';
+
+ @override
+ String get mapOsmParks => '公園';
+
+ @override
+ String get mapOsmLandUse => '土地利用';
+
+ @override
+ String get mapOsmAirportAreas => '空港エリア';
+
+ @override
+ String get mapOsmWater => '水域';
+
+ @override
+ String get mapOsmRivers => '河川';
+
+ @override
+ String get mapOsmBoundaries => '境界';
+
+ @override
+ String get mapOsmBuildings => '建物';
+
+ @override
+ String get mapOsmRoads => '道路';
+
+ @override
+ String get mapOsmRoadNames => '道路名';
+
+ @override
+ String get mapOsmWaterNames => '水域名';
+
+ @override
+ String get mapOsmPeaks => '山頂';
+
+ @override
+ String get mapOsmAirportNames => '空港名';
+
+ @override
+ String get mapOsmPlaceNames => '地名';
+
+ @override
+ String get mapOsmPoi => '注目施設';
+
+ @override
+ String get mapOsmHouseNumbers => '住居表示';
+
+ @override
+ String get mapOsmRestoreAll => 'すべて復元';
+
+ @override
+ String get mapOsmSectionNatural => '自然地物';
+
+ @override
+ String get mapOsmSectionRoadsAndBuildings => '道路と建物';
+
+ @override
+ String get mapOsmSectionLabelsAndPlaces => 'ラベルと場所';
+
@override
String get mapTownLabels => '郷鎮名';
@@ -2281,10 +2391,10 @@ class AppLocalizationsJa extends AppLocalizations {
String get notifySetFailed => '設定を保存できませんでした。もう一度お試しください。';
@override
- String get meshtasticDisconnect => 'Disconnect';
+ String get meshtasticDisconnect => '切断';
@override
- String get meshtasticUndecoded => 'Not decrypted';
+ String get meshtasticUndecoded => '復号されていません';
@override
String get notifyAnnouncement => 'お知らせ';
@@ -2820,6 +2930,51 @@ class AppLocalizationsJa extends AppLocalizations {
return '「$what」は拒否されており、システムは再度確認しません。設定から許可してください。';
}
+ @override
+ String get permissionGuideNotification => 'システム設定から通知を許可してください。';
+
+ @override
+ String get permissionGuideForegroundLocation => 'システム設定から正確な位置情報を許可してください。';
+
+ @override
+ String permissionGuideBackgroundLocation(Object option) {
+ return '「$option」で「常に許可」を選択してください。';
+ }
+
+ @override
+ String get permissionGuideBackgroundExecution =>
+ 'システム設定でバックグラウンド実行を許可し、通知が停止されないようにしてください。';
+
+ @override
+ String get permissionGuideUnusedPause =>
+ 'アプリが「未使用」と表示される場合は、システム設定で「許可」を選択してください。';
+
+ @override
+ String get permissionGuideUnusedFreeSpace =>
+ 'ストレージ不足で一時停止された場合は、キャッシュを削除して再度開いてください。';
+
+ @override
+ String get permissionGuideUnusedRevoke =>
+ 'アプリの権限が取り消された場合は、システム設定で再度許可してください。';
+
+ @override
+ String get permissionGuideUnusedPlayProtect =>
+ 'Play プロテクトが一時停止した場合は、Google Play でアプリの状態を確認してください。';
+
+ @override
+ String permissionGuideVendorPower(Object vendor) {
+ return '「$vendor」の省電力設定で、このアプリを「制限なし」に設定してください。';
+ }
+
+ @override
+ String get permissionStillRequired => 'まだ必要です。設定から有効にしてください。';
+
+ @override
+ String get permissionVerifyManually => 'システム設定でこの権限が有効かどうか手動で確認してください。';
+
+ @override
+ String get permissionBackgroundLocationOption => '「常に許可」';
+
@override
String get displayTextSize => '文字サイズ';
@@ -2959,6 +3114,16 @@ class AppLocalizationsJa extends AppLocalizations {
@override
String get moreDumpDiagnosticsHint => 'アップロードしてリンクをコピーします';
+ @override
+ String get dumpIncludeSensitive => '正確な位置情報を含める';
+
+ @override
+ String get dumpIncludeSensitiveHint =>
+ 'ログとバックグラウンド位置情報の座標を含めます。未選択の場合は null に置き換えます';
+
+ @override
+ String get dumpUpload => 'アップロード';
+
@override
String get dumpUploaded => 'アップロードしました';
diff --git a/lib/l10n/gen/app_localizations_ko.dart b/lib/l10n/gen/app_localizations_ko.dart
index 86937c010..cbe9175f4 100644
--- a/lib/l10n/gen/app_localizations_ko.dart
+++ b/lib/l10n/gen/app_localizations_ko.dart
@@ -55,7 +55,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get restroomTypeMale => '남자 화장실';
@override
- String get meshtasticLastReceived => 'Last received';
+ String get meshtasticLastReceived => '마지막 수신';
@override
String get reportDetailSortByCounty => '지역순 정렬';
@@ -86,7 +86,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get homeRainTrendScattered => '약한 비가 올 수 있어요';
@override
- String get meshtasticUptime => 'Uptime';
+ String get meshtasticUptime => '가동 시간';
@override
String get weatherRankingTempExtremes => '기온 극값';
@@ -98,7 +98,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapTerrainReliefHint => '기본 지도에 지형 음영 표시';
@override
- String get meshtasticEmptyMessage => '(empty message)';
+ String get meshtasticEmptyMessage => '(빈 메시지)';
@override
String get moreSectionRegion => '지역';
@@ -110,7 +110,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get aedHoursSaturday => '토요일 운영시간';
@override
- String get moonPhaseNew => 'New moon';
+ String get moonPhaseNew => '신월';
@override
String get notifySectionEew => '지진 조기경보';
@@ -125,7 +125,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapTownLabelsHint => '확대하면 읍면동 이름 표시';
@override
- String get commonCancel => 'Cancel';
+ String get commonCancel => '취소';
@override
String get notifyOptTsunamiWarning => '지진해일 경보만';
@@ -217,8 +217,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get reportFilterOrderDesc => '내림차순';
@override
- String get meshtasticExcludeMqttSubtitle =>
- 'Nodes bridged over the internet, not heard by radio';
+ String get meshtasticExcludeMqttSubtitle => '인터넷으로 연결된 노드(무선으로는 수신되지 않음)';
@override
String get reportFilterIntensityInfoTitle => '진도 신제·구제';
@@ -230,14 +229,13 @@ class AppLocalizationsKo extends AppLocalizations {
String get radarOverlayMenuTooltip => '레이더 레이어 옵션';
@override
- String get meshtasticNodes => 'Nodes';
+ String get meshtasticNodes => '노드';
@override
- String get meshtasticSend => 'Send';
+ String get meshtasticSend => '보내기';
@override
- String get typhoonOverlayStormL7Tooltip =>
- 'Level-7 wind field + average circle (purple)';
+ String get typhoonOverlayStormL7Tooltip => '레벨 7 바람장 + 평균 반경(보라색)';
@override
String get aedType => '유형';
@@ -289,7 +287,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get skyTimeDusk => '땅거미';
@override
- String get meshtasticFirmware => 'Firmware';
+ String get meshtasticFirmware => '펌웨어';
@override
String get reportFilterDateEndNote => '종료일: 당일 24:00(타이베이)';
@@ -298,7 +296,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get reportFilterSortMagnitude => '규모';
@override
- String get meshtasticSilent => 'Silent';
+ String get meshtasticSilent => '무음';
@override
String get mapLayerCategoryEarthquake => '지진';
@@ -332,7 +330,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get notifyOptTsunamiAll => '지진해일 주의보 및 경보';
@override
- String get meshtasticLayerOptions => 'Node options';
+ String get meshtasticLayerOptions => '노드 옵션';
@override
String get onboardingAgreeContinue => '동의하고 계속';
@@ -341,7 +339,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get commonRetry => '다시 시도';
@override
- String get meshtasticNodeId => 'Node ID';
+ String get meshtasticNodeId => '노드 ID';
@override
String reportDetailNumbered(String number) {
@@ -349,7 +347,7 @@ class AppLocalizationsKo extends AppLocalizations {
}
@override
- String get typhoonOverlayStormBandSubtitle => 'With average circle';
+ String get typhoonOverlayStormBandSubtitle => '평균 반경 포함';
@override
String get disasterMapOverlayRestroomTooltip => '공중화장실 표시';
@@ -376,13 +374,13 @@ class AppLocalizationsKo extends AppLocalizations {
String get sponsorRestore => '구매 복원';
@override
- String get meshtasticChannelWorking => 'Setting up the DPIP channel…';
+ String get meshtasticChannelWorking => 'DPIP 채널 설정 중…';
@override
- String get meshtasticRegionSwitch => 'Switch to TW';
+ String get meshtasticRegionSwitch => 'TW 지역으로 전환';
@override
- String get meshtasticTraffic => 'Traffic';
+ String get meshtasticTraffic => '트래픽';
@override
String get mapLayerStyleBdTooltip => 'Dvorak BD 커브——열대저기압 강도 분석용 계단 그레이스케일';
@@ -397,7 +395,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapLayerSatelliteTransparentNight => '야간 = 투명,배경 지도 표시';
@override
- String get meshtasticScanning => 'Scanning…';
+ String get meshtasticScanning => '스캔 중…';
@override
String regionSelectFull(int max) {
@@ -469,7 +467,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get navMore => '더보기';
@override
- String get meshtasticDpipChannel => 'DPIP channel';
+ String get meshtasticDpipChannel => 'DPIP 채널';
@override
String get disasterMapOverlaySectionLayers => '레이어';
@@ -481,7 +479,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get typhoonLabelNe => 'NE';
@override
- String get meshtasticCopied => 'Message copied';
+ String get meshtasticCopied => '메시지를 복사했습니다';
@override
String get reportListEmpty => '지진 보고서가 없습니다';
@@ -493,19 +491,19 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapLayerSatelliteTruecolor => '히마와리 트루컬러';
@override
- String get typhoonOverlaySectionExtra => 'Overlays';
+ String get typhoonOverlaySectionExtra => '오버레이';
@override
String get eewSWave => 'S파';
@override
- String get meshtasticBusyTitle => 'Another app is using this radio';
+ String get meshtasticBusyTitle => '다른 앱이 이 무전기를 사용 중입니다';
@override
String get restroomCategoryCultural => '문화·여가 시설';
@override
- String get typhoonLabelWind => 'Max. sustained wind near centre';
+ String get typhoonLabelWind => '중심 부근 최대 지속 풍속';
@override
String get radarGlobalOutlineHint => '각국 국경선';
@@ -517,7 +515,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get typhoonLegendCircle15 => '강풍권 (7급)';
@override
- String get dataSectionAstronomy => 'Astronomy';
+ String get dataSectionAstronomy => '천문';
@override
String get homeRainTrendLightSustained => '앞으로 1시간 동안 약한 비가 이어질 거예요';
@@ -526,10 +524,10 @@ class AppLocalizationsKo extends AppLocalizations {
String get commonError => '문제가 발생했습니다';
@override
- String get moonPhaseWaningCrescent => 'Waning crescent';
+ String get moonPhaseWaningCrescent => '그믐달';
@override
- String get meshtasticPower => 'Power';
+ String get meshtasticPower => '전원';
@override
String get mapTimelineNow => '현재';
@@ -557,7 +555,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get notifyTitle => '알림';
@override
- String get meshtasticTxPower => 'TX power';
+ String get meshtasticTxPower => 'TX 전력';
@override
String get restroomCategoryLabel => '구분';
@@ -570,7 +568,7 @@ class AppLocalizationsKo extends AppLocalizations {
'DPIP는 실시간 재난 예방 정보를 제공하는 데 전념하며, 광고나 다른 수익 모델이 없습니다. 여러분의 후원은 서버 운영과 지속적인 개발에 도움이 됩니다.';
@override
- String get typhoonLabelStormAvg => 'Avg. radius of Beaufort 10 winds';
+ String get typhoonLabelStormAvg => '보퍼트 10 풍속 평균 반경';
@override
String get restroomCategoryCommercial => '상업·영업 시설';
@@ -604,7 +602,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get restroomTypeUnspecified => '미설정';
@override
- String get typhoonOverlayProbabilityHint => 'Hides the forecast cone';
+ String get typhoonOverlayProbabilityHint => '예상 이동 경로를 숨깁니다';
@override
String get mapLayerSatelliteGlobalOutline => '국경선';
@@ -641,8 +639,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get aedDescription => '비고';
@override
- String get typhoonOverlayWeatherRadarTooltip =>
- 'Radar echo closest to the typhoon bulletin time';
+ String get typhoonOverlayWeatherRadarTooltip => '태풍 정보 시간과 가장 가까운 레이더 에코';
@override
String get onboardingPermLocationDesc => '현재 위치에 맞춰 경보를 전달합니다.';
@@ -654,13 +651,13 @@ class AppLocalizationsKo extends AppLocalizations {
String get homeActiveEventsEmpty => '발효 중인 이벤트가 없습니다';
@override
- String get typhoonLabelPosition => 'Centre location';
+ String get typhoonLabelPosition => '중심 위치';
@override
String get weatherRankingBy => '정렬';
@override
- String get typhoonIntensityMild => 'Mild typhoon';
+ String get typhoonIntensityMild => '약한 태풍';
@override
String get windForecastGlobalOutlineHint => '각국 국경선';
@@ -678,7 +675,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get restroomCategoryReligious => '종교·의례 시설';
@override
- String get meshtasticRole => 'Role';
+ String get meshtasticRole => '역할';
@override
String get mapLayerSatelliteCloudCloudy => '구름';
@@ -690,7 +687,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get meshtasticJumpToLatest => '최신으로 이동';
@override
- String get meshtasticNoMessages => 'No messages yet';
+ String get meshtasticNoMessages => '아직 메시지가 없습니다';
@override
String get onboardingPermNotifyDesc => '지진, 날씨, 재해가 발생하는 즉시 경보를 전달합니다.';
@@ -708,7 +705,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get moreGooglePlay => 'Google Play';
@override
- String get meshtasticOnline => 'Heard recently';
+ String get meshtasticOnline => '최근 수신됨';
@override
String get typhoonLabelSw => 'SW';
@@ -754,7 +751,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get eewArrived => '도달';
@override
- String get meshtasticNoDevices => 'No Meshtastic devices found';
+ String get meshtasticNoDevices => 'Meshtastic 기기를 찾을 수 없습니다';
@override
String get mapLayerCategoryLife => '생활';
@@ -763,10 +760,10 @@ class AppLocalizationsKo extends AppLocalizations {
String get reportFilterSortIntensity => '진도';
@override
- String get meshtasticStateDisconnected => 'Disconnected';
+ String get meshtasticStateDisconnected => '연결 해제됨';
@override
- String get typhoonIntensityIntense => 'Intense typhoon';
+ String get typhoonIntensityIntense => '강한 태풍';
@override
String get mapLayerOrderTitle => '레이어 순서';
@@ -775,7 +772,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get dpmYes => '예';
@override
- String get meshtasticNoHistory => 'Not enough history yet';
+ String get meshtasticNoHistory => '아직 기록이 부족합니다';
@override
String get reportDetailLocalIntensityUnavailable => '진도 정보 없음';
@@ -802,10 +799,10 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapLayerSatelliteMndwi => '히마와리 MNDWI';
@override
- String get typhoonOverlaySectionStorm => 'Storm wind';
+ String get typhoonOverlaySectionStorm => '폭풍 바람';
@override
- String get moonPhaseFull => 'Full moon';
+ String get moonPhaseFull => '보름달';
@override
String meshtasticBinaryPayload(String size) {
@@ -813,14 +810,14 @@ class AppLocalizationsKo extends AppLocalizations {
}
@override
- String get moonPhaseWaningGibbous => 'Waning gibbous';
+ String get moonPhaseWaningGibbous => '하현망월';
@override
String get reportFilterIntensityInfoModernTitle => '신제(2020년 이후)';
@override
String typhoonDataTime(String time) {
- return 'Data time\n$time';
+ return '자료 시간\n$time';
}
@override
@@ -830,7 +827,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get moreSectionAbout => '정보';
@override
- String get meshtasticSelectDevice => 'Select a radio';
+ String get meshtasticSelectDevice => '무전기 선택';
@override
String get onboardingIntroBody =>
@@ -843,19 +840,19 @@ class AppLocalizationsKo extends AppLocalizations {
String get reportDetailImage => '지진 보고서 이미지';
@override
- String get meshtasticStateConfiguring => 'Configuring…';
+ String get meshtasticStateConfiguring => '구성 중…';
@override
- String get typhoonLabelGaleAvg => 'Avg. radius of Beaufort 7 winds';
+ String get typhoonLabelGaleAvg => '보퍼트 7 풍속 평균 반경';
@override
String get onboardingPermNotify => '알림';
@override
- String get meshtasticClearMessages => 'Clear messages';
+ String get meshtasticClearMessages => '메시지 지우기';
@override
- String get meshtasticNotifyMessages => 'Notify on new messages';
+ String get meshtasticNotifyMessages => '새 메시지 알림';
@override
String get defaultMapLayerSettings => '지도 기본 레이어';
@@ -930,7 +927,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapTimelineFuture => '미래';
@override
- String get typhoonLegendCircleAvg => 'Average circle';
+ String get typhoonLegendCircleAvg => '평균 반경';
@override
String reportFilterDepthKm(String depth) {
@@ -949,7 +946,7 @@ class AppLocalizationsKo extends AppLocalizations {
}
@override
- String get typhoonLabelGust => 'Peak gust';
+ String get typhoonLabelGust => '최대 돌풍';
@override
String get mapAppGoogleMaps => 'Google Maps';
@@ -967,7 +964,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get skyTimeGolden => '골든아워';
@override
- String get moonAge => 'Age';
+ String get moonAge => '월령';
@override
String get meshtasticRadioSettings => 'LoRa';
@@ -982,7 +979,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapLayers => '레이어';
@override
- String get meshtasticHardware => 'Hardware';
+ String get meshtasticHardware => '하드웨어';
@override
String get languageSettings => '언어';
@@ -996,7 +993,7 @@ class AppLocalizationsKo extends AppLocalizations {
}
@override
- String get typhoonOverlayWeatherHint => 'Aligned to bulletin time';
+ String get typhoonOverlayWeatherHint => '정보 시간에 맞춤';
@override
String get skyTimeDawn => '여명';
@@ -1005,7 +1002,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get skyTimeAfternoon => '오후';
@override
- String get meshtasticLastHeard => 'Last heard';
+ String get meshtasticLastHeard => '마지막 수신';
@override
String get typhoonWarningTitle => '태풍 경보';
@@ -1055,11 +1052,10 @@ class AppLocalizationsKo extends AppLocalizations {
String get navEarthquake => '지진';
@override
- String get typhoonOverlayStormL10Tooltip =>
- 'Level-10 wind field + average circle (yellow)';
+ String get typhoonOverlayStormL10Tooltip => '레벨 10 바람장 + 평균 반경(노란색)';
@override
- String get moonPhaseWaxingGibbous => 'Waxing gibbous';
+ String get moonPhaseWaxingGibbous => '상현망월';
@override
String get reportDetailTitle => '지진 보고서';
@@ -1073,10 +1069,10 @@ class AppLocalizationsKo extends AppLocalizations {
}
@override
- String get meshtasticNoNodes => 'No nodes heard yet';
+ String get meshtasticNoNodes => '아직 노드가 감지되지 않았습니다';
@override
- String get meshtasticViaMqtt => 'Via MQTT (internet)';
+ String get meshtasticViaMqtt => 'MQTT 경유(인터넷)';
@override
String get radarCountyOutline => '시·군 경계';
@@ -1094,11 +1090,10 @@ class AppLocalizationsKo extends AppLocalizations {
String get changelogCurrentVersion => '현재';
@override
- String get typhoonLabelPressure => 'Central pressure';
+ String get typhoonLabelPressure => '중심 기압';
@override
- String get typhoonOverlayForecastCalloutsTooltip =>
- 'Show forecast-point detail cards when zoomed in';
+ String get typhoonOverlayForecastCalloutsTooltip => '확대 시 예상 지점 상세 카드 표시';
@override
String get aedOpenRemark => '운영시간 비고';
@@ -1108,7 +1103,7 @@ class AppLocalizationsKo extends AppLocalizations {
'재해가 발생하는 즉시 알려드릴 수 있도록 다음 권한을 허용해 주세요. 시스템 설정에서 언제든지 변경할 수 있습니다.';
@override
- String get typhoonOverlaySectionWeather => 'Weather underlay';
+ String get typhoonOverlaySectionWeather => '날씨 배경';
@override
String get notifyOptWeatherLocal => '현재 위치만';
@@ -1117,7 +1112,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapNavRain => '강우';
@override
- String get moonDays => 'days';
+ String get moonDays => '일';
@override
String mapLegendUnit(String unit) {
@@ -1128,7 +1123,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get weatherModeClear => '맑음';
@override
- String get meshtasticRadio => 'Radio';
+ String get meshtasticRadio => '무전기';
@override
String get commonEmpty => '표시할 내용이 없습니다';
@@ -1137,10 +1132,10 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapLayerSatelliteB01 => '히마와리 가시 청색(B01)';
@override
- String get meshtasticExternalPower => 'External power';
+ String get meshtasticExternalPower => '외부 전원';
@override
- String get moonPhaseLastQuarter => 'Last quarter';
+ String get moonPhaseLastQuarter => '하현';
@override
String get reportFilterOrderAsc => '오름차순';
@@ -1167,19 +1162,19 @@ class AppLocalizationsKo extends AppLocalizations {
String get restroomGradeExcellent => '최우수';
@override
- String get meshtasticLastSent => 'Last sent';
+ String get meshtasticLastSent => '마지막 전송';
@override
- String get meshtasticName => 'Name';
+ String get meshtasticName => '이름';
@override
- String get meshtasticScan => 'Scan';
+ String get meshtasticScan => '스캔';
@override
String get mapLayerCategoryForecast => '수치 예보';
@override
- String get meshtasticChannelFailed => 'Couldn\'t set up the DPIP channel';
+ String get meshtasticChannelFailed => 'DPIP 채널을 설정하지 못했습니다';
@override
String get themeSystem => '시스템';
@@ -1199,7 +1194,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get weatherPrecipitation => '강수량';
@override
- String get moonNextFullMoon => 'Next full moon';
+ String get moonNextFullMoon => '다음 보름달';
@override
String get dpmSheetEmpty => '지도에서 마커를 눌러 상세 보기';
@@ -1228,7 +1223,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get typhoonLabelNw => 'NW';
@override
- String get moonPhaseWaxingCrescent => 'Waxing crescent';
+ String get moonPhaseWaxingCrescent => '초승달';
@override
String get restroomCategoryLeisure => '휴양·오락 시설';
@@ -1240,23 +1235,22 @@ class AppLocalizationsKo extends AppLocalizations {
String get aedCategory => '분류';
@override
- String get meshtasticChannels => 'Channels';
+ String get meshtasticChannels => '채널';
@override
String get monitorWaiting => '데이터 대기 중…';
@override
- String get typhoonOverlayForecastCallouts => 'Forecast tooltips';
+ String get typhoonOverlayForecastCallouts => '예상 도구 설명';
@override
String get reportDetailEpicenter => '진앙 좌표';
@override
- String get meshtasticVoltage => 'Voltage';
+ String get meshtasticVoltage => '전압';
@override
- String get mapLayerMeshtasticSubtitle =>
- 'LoRa mesh nodes heard by your radio';
+ String get mapLayerMeshtasticSubtitle => '무전기로 들은 LoRa 메시 노드';
@override
String get mapLayerWind => '바람';
@@ -1317,7 +1311,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get reportFilterIntensityInfoLegacyTitle => '구제(2020년 이전)';
@override
- String get typhoonLabelSpeed => 'Past movement speed';
+ String get typhoonLabelSpeed => '이동 속도';
@override
String mapAppOpenFailed(String app) {
@@ -1328,7 +1322,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapLayerSatelliteRgbComposite => 'RGB 합성(JMA 레시피)';
@override
- String get meshtasticReceived => 'Received';
+ String get meshtasticReceived => '수신';
@override
String get weatherRankingExtremeLow => '오늘 최저';
@@ -1346,10 +1340,10 @@ class AppLocalizationsKo extends AppLocalizations {
String get shelterCategoryLabel => '적용 재해';
@override
- String get meshtasticStateConnecting => 'Connecting…';
+ String get meshtasticStateConnecting => '연결 중…';
@override
- String get moonTitle => 'Moon';
+ String get moonTitle => '달';
@override
String get weatherRankingGust => '돌풍';
@@ -1364,7 +1358,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get notifySectionWeather => '날씨';
@override
- String get meshtasticPreset => 'Modem preset';
+ String get meshtasticPreset => '모뎀 프리셋';
@override
String get dataSectionSeismic => '지진';
@@ -1391,13 +1385,13 @@ class AppLocalizationsKo extends AppLocalizations {
String get regionCurrent => '현재 위치';
@override
- String get meshtasticNotConnected => 'Not connected to a radio';
+ String get meshtasticNotConnected => '무전기에 연결되지 않음';
@override
String get weatherModeSnow => '눈';
@override
- String get mapLayerMeshtastic => 'Meshtastic nodes';
+ String get mapLayerMeshtastic => 'Meshtastic 노드';
@override
String get moreDeveloper => '디버그 정보';
@@ -1406,7 +1400,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapLayerSatelliteB14 => '히마와리 장파 적외(B14)';
@override
- String get meshtasticChannelUse => 'Channel use';
+ String get meshtasticChannelUse => '채널 사용률';
@override
String get mapNavLightning => '번개';
@@ -1430,7 +1424,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get dpmOpenInMaps => '지도에서 열기';
@override
- String get meshtasticNotifyNodes => 'Notify on new nodes';
+ String get meshtasticNotifyNodes => '새 노드 알림';
@override
String get onboardingPermCriticalDesc =>
@@ -1440,7 +1434,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapLayerSatelliteTransparentWarm => '맑음(고온부) = 투명,배경 지도 표시';
@override
- String get meshtasticSent => 'Sent';
+ String get meshtasticSent => '전송됨';
@override
String get homeForecastTitle => '24시간 예보';
@@ -1450,7 +1444,7 @@ class AppLocalizationsKo extends AppLocalizations {
@override
String meshtasticExcludeMqttHidden(int count) {
- return '$count hidden';
+ return '$count개 숨김';
}
@override
@@ -1466,13 +1460,13 @@ class AppLocalizationsKo extends AppLocalizations {
String get reportListToday => '오늘';
@override
- String get meshtasticTapNode => 'Tap a node for details';
+ String get meshtasticTapNode => '노드를 탭하여 자세히 보기';
@override
String get commonLoading => '불러오는 중…';
@override
- String get typhoonIntensityModerate => 'Moderate typhoon';
+ String get typhoonIntensityModerate => '중간 강도 태풍';
@override
String get mapLayerSatelliteAsh => '히마와리 화산재';
@@ -1484,13 +1478,13 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapLayerCategorySatellite => '위성';
@override
- String get meshtasticChannelReady => 'DPIP channel ready';
+ String get meshtasticChannelReady => 'DPIP 채널 준비 완료';
@override
String get mapLayerSatelliteNightmicrophysics => '히마와리 야간 미세물리';
@override
- String get typhoonIntensityTd => 'Tropical depression';
+ String get typhoonIntensityTd => '열대 저기압';
@override
String get reportFilterDate => '날짜';
@@ -1563,7 +1557,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapLayerSatelliteBtdSo2 => '히마와리 이산화황/구름상';
@override
- String get meshtasticStateError => 'Error';
+ String get meshtasticStateError => '오류';
@override
String get weatherModeOvercast => '흐림';
@@ -1572,8 +1566,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get reportDetailDepth => '진원 깊이';
@override
- String get typhoonOverlayWarningTooltip =>
- 'Highlight counties under a typhoon warning';
+ String get typhoonOverlayWarningTooltip => '태풍 경보 지역 강조';
@override
String get reportFilterDatePick => '날짜 선택';
@@ -1588,7 +1581,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get shelterOutdoorLabel => '실외 수용';
@override
- String get meshtasticStateConnected => 'Connected';
+ String get meshtasticStateConnected => '연결됨';
@override
String get mapNavRadar => '레이더';
@@ -1605,8 +1598,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get locationBannerPermission => '위치 권한이 꺼져 있어 지역 맞춤 경보를 받을 수 없습니다.';
@override
- String get typhoonOverlayWeatherNoneTooltip =>
- 'No radar or infrared underlay';
+ String get typhoonOverlayWeatherNoneTooltip => '레이더 또는 적외선 배경 없음';
@override
String get radarCountyOutlineHint => '에코 위에 표시';
@@ -1618,13 +1610,13 @@ class AppLocalizationsKo extends AppLocalizations {
String get homeRainTrendTitle => '향후 1시간 강수';
@override
- String get moonPhaseFirstQuarter => 'First quarter';
+ String get moonPhaseFirstQuarter => '상현';
@override
String get mapLayerCategoryTyphoon => '태풍';
@override
- String get meshtasticUtilization => 'Airtime (24h)';
+ String get meshtasticUtilization => '에어타임(24시간)';
@override
String get restroomTypeMixed => '남녀 공용 화장실';
@@ -1642,7 +1634,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapLayerSatelliteBtdWvirw => '히마와리 오버슈팅 탑';
@override
- String get meshtasticReadingAge => 'Reading taken';
+ String get meshtasticReadingAge => '측정 시각';
@override
String get mapAppCallFailed => '이 기기에서는 전화를 걸 수 없습니다';
@@ -1663,7 +1655,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get reportDetailLocalFelt => '국지적 유감지진';
@override
- String get meshtasticDevice => 'Device';
+ String get meshtasticDevice => '기기';
@override
String get onboardingGrant => '허용';
@@ -1711,7 +1703,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get reportListEmptyFiltered => '조건에 맞는 지진 보고서가 없습니다';
@override
- String get meshtasticExcludeMqtt => 'Hide MQTT nodes';
+ String get meshtasticExcludeMqtt => 'MQTT 노드 숨기기';
@override
String get mapNavTyphoon => '태풍';
@@ -1749,13 +1741,13 @@ class AppLocalizationsKo extends AppLocalizations {
String get navHome => '홈';
@override
- String get meshtasticRegionLabel => 'Region';
+ String get meshtasticRegionLabel => '지역';
@override
String get mapLayerSatelliteCloudtop => '히마와리 운정 온도';
@override
- String get moonTimelineCaption => 'Phase';
+ String get moonTimelineCaption => '위상';
@override
String get openSourceLicenses => '오픈소스 라이선스';
@@ -1775,7 +1767,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get radarScanRange => '스캔 범위 표시';
@override
- String get meshtasticHopLimit => 'Hop limit';
+ String get meshtasticHopLimit => '홉 제한';
@override
String get weatherRankingExtremeHigh => '오늘 최고';
@@ -1790,7 +1782,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapLayerSatelliteNaturalcolor => '히마와리 내추럴컬러';
@override
- String get meshtasticAirtime => 'Air time (TX)';
+ String get meshtasticAirtime => '에어타임(TX)';
@override
String shelterCapacityValue(int n) {
@@ -1803,7 +1795,7 @@ class AppLocalizationsKo extends AppLocalizations {
}
@override
- String get meshtasticSendHint => 'Message to broadcast';
+ String get meshtasticSendHint => '브로드캐스트할 메시지';
@override
String monitorDelay(String value) {
@@ -1817,21 +1809,20 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapLayerSatelliteB08 => '히마와리 상층 수증기(B08)';
@override
- String get meshtasticReconnecting => 'Reconnecting…';
+ String get meshtasticReconnecting => '다시 연결 중…';
@override
String get radarTownOutlineSubtitle => '레이더 에코 아래에서도 읍·면·동 경계가 보이도록 합니다.';
@override
- String get typhoonOverlayWeatherSatelliteTooltip =>
- 'Infrared closest to the typhoon bulletin time';
+ String get typhoonOverlayWeatherSatelliteTooltip => '태풍 정보 시간과 가장 가까운 적외선';
@override
String get radarScanRangeHint => '범위 밖 공백은 미관측';
@override
String typhoonPickerTd(String no) {
- return 'Tropical depression TD $no';
+ return '열대 저기압 TD $no';
}
@override
@@ -1979,49 +1970,49 @@ class AppLocalizationsKo extends AppLocalizations {
String get endpointServiceRts => 'RTS';
@override
- String get endpointServiceRadar => 'Radar';
+ String get endpointServiceRadar => '레이더';
@override
- String get endpointServiceSatellite => 'Satellite';
+ String get endpointServiceSatellite => '위성';
@override
String get endpointServiceQpesums => 'QPE';
@override
- String get endpointServiceWind => 'Wind';
+ String get endpointServiceWind => '바람';
@override
- String get endpointServiceDpm => 'Disaster points';
+ String get endpointServiceDpm => '재해 지점';
@override
- String get endpointServiceWeather => 'Weather';
+ String get endpointServiceWeather => '날씨';
@override
- String get endpointServiceRain => 'Rain';
+ String get endpointServiceRain => '비';
@override
- String get endpointServiceLightning => 'Lightning';
+ String get endpointServiceLightning => '번개';
@override
- String get endpointServiceTyphoon => 'Typhoon';
+ String get endpointServiceTyphoon => '태풍';
@override
- String get endpointServiceReport => 'EQ reports';
+ String get endpointServiceReport => '지진 보고';
@override
- String get endpointServiceTremStation => 'Tremor station';
+ String get endpointServiceTremStation => '진도 관측소';
@override
- String get endpointServiceEvent => 'Events';
+ String get endpointServiceEvent => '이벤트';
@override
- String get endpointServiceLocation => 'Location';
+ String get endpointServiceLocation => '위치';
@override
- String get endpointServiceNotify => 'Notifications';
+ String get endpointServiceNotify => '알림';
@override
- String get endpointServiceOther => 'Other';
+ String get endpointServiceOther => '기타';
@override
String get feedConnecting => '연결 중…';
@@ -2044,17 +2035,16 @@ class AppLocalizationsKo extends AppLocalizations {
@override
String get meshtasticBusyBody =>
- 'Disconnect it in the other Meshtastic app first. Two apps on one radio take each other\'s messages, so some will go missing.';
+ '먼저 다른 Meshtastic 앱에서 무전기를 연결 해제하세요. 무전기 하나를 두 앱이 함께 쓰면 서로의 메시지를 가로채 일부가 유실됩니다.';
@override
- String get meshtasticChannelNoSlot =>
- 'No free channel slot — free one on the radio';
+ String get meshtasticChannelNoSlot => '빈 채널 슬롯이 없습니다 — 무전기에서 하나를 비우세요';
@override
String get restroomCategoryTransport => '교통';
@override
- String get meshtasticBattery => 'Battery';
+ String get meshtasticBattery => '배터리';
@override
String get meshtasticDistance => '거리';
@@ -2066,14 +2056,14 @@ class AppLocalizationsKo extends AppLocalizations {
String get meshtasticBatteryTrend => '배터리 추이';
@override
- String get typhoonOverlayMenuTooltip => 'Typhoon overlay options';
+ String get typhoonOverlayMenuTooltip => '태풍 오버레이 옵션';
@override
String get mapLayerSatelliteBtdOzone => '히마와리 대류권계면';
@override
String meshtasticRegionMismatch(String region) {
- return 'Radio region is $region — DPIP needs TW';
+ return '무전기 지역은 $region입니다 — DPIP는 TW가 필요합니다';
}
@override
@@ -2103,10 +2093,15 @@ class AppLocalizationsKo extends AppLocalizations {
String get moreVersionStable => '정식 버전';
@override
- String get moreVersionNotes => '현재 버전';
+ String get moreVersionNotes => '이번 업데이트';
@override
- String get releaseHighlightsTitle => '이번 업데이트';
+ String get moreVersionNotesHighlightsSubtitle => '이번 버전의 변경 사항';
+
+ @override
+ String releaseHighlightsTitle(Object train) {
+ return '$train 주요 내용';
+ }
@override
String get releaseHighlightsTabNormal => '변경된 점';
@@ -2149,7 +2144,7 @@ class AppLocalizationsKo extends AppLocalizations {
'진도는 0–4, 5약, 5강, 6약, 6강, 7입니다. 필터는 신제를 따르며, 이전 지진은 목록에서 구제 표기로 표시됩니다.';
@override
- String get typhoonOverlayWeatherNone => 'None';
+ String get typhoonOverlayWeatherNone => '없음';
@override
String get mapLayerStyleGray => '그레이스케일(JMA)';
@@ -2158,7 +2153,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get weatherModeAuto => '자동';
@override
- String get typhoonLabelProbCircle => '70% probability circle';
+ String get typhoonLabelProbCircle => '70% 확률 원';
@override
String get notifyOptAll => '전체 수신';
@@ -2170,7 +2165,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapLayerSatelliteB07 => '히마와리 단파 적외(B07)';
@override
- String get typhoonLabelDirection => 'Past movement direction';
+ String get typhoonLabelDirection => '이동 방향';
@override
String get regionManageTitle => '저장한 지역';
@@ -2195,7 +2190,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get rainInterval10m => '10분';
@override
- String get meshtasticConnectAnyway => 'Connect anyway';
+ String get meshtasticConnectAnyway => '그래도 연결';
@override
String reportListDayCount(int count) {
@@ -2218,8 +2213,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapLayerShelter => '대피소';
@override
- String get typhoonOverlayProbabilityTooltip =>
- 'Show strike probability (hides the forecast cone)';
+ String get typhoonOverlayProbabilityTooltip => '강타 확률 표시(예상 이동 경로 숨김)';
@override
String get mapLayerSatelliteNdwi => '히마와리 NDWI';
@@ -2240,7 +2234,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get mapLayerCategoryRadar => '레이더';
@override
- String get meshtasticShortName => 'Short name';
+ String get meshtasticShortName => '짧은 이름';
@override
String get mapLayerSatelliteAirmass => '히마와리 에어매스';
@@ -2267,7 +2261,7 @@ class AppLocalizationsKo extends AppLocalizations {
@override
String get meshtasticRegionConfirm =>
- 'Switch this radio to the TW region? It restarts and disconnects for a moment, and every other channel on it moves too.';
+ '이 무전기를 TW 지역으로 전환할까요? 잠시 재시작되고 연결이 끊기며, 다른 모든 채널도 이동합니다.';
@override
String get dataEarthquakeSubtitle => '지진 보고서';
@@ -2284,6 +2278,113 @@ class AppLocalizationsKo extends AppLocalizations {
@override
String get onboardingTermsTitle => '서비스 약관';
+ @override
+ String get mapOsmOverlay => '상세 지도';
+
+ @override
+ String get mapOsmOverlayHint => '도로, 건물 및 지명을 더 자세히 표시';
+
+ @override
+ String get mapOsmDetails => '상세 지도 레이어';
+
+ @override
+ String get moreDataSources => '데이터 출처';
+
+ @override
+ String get dataSourceTremNet => '探索智慧科技有限公司 — TREM-Net';
+
+ @override
+ String get dataSourceCwa => '交通部中央氣象署 (CWA)';
+
+ @override
+ String get dataSourceJma => '気象庁 (JMA)';
+
+ @override
+ String get dataSourceNcdr => '國家災害防救科技中心 (NCDR)';
+
+ @override
+ String get dataSourceEcmwf =>
+ 'European Centre for Medium-Range Weather Forecasts (ECMWF)';
+
+ @override
+ String get dataSourceNoaaGfs =>
+ 'National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)';
+
+ @override
+ String get dataSourceGovernmentOpenData => '政府資料開放平臺';
+
+ @override
+ String get dataSourceOpenStreetMap => '© OpenStreetMap contributors';
+
+ @override
+ String get dataSourceNasaMoon =>
+ 'National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)';
+
+ @override
+ String mapOsmDetailsHint(int enabled, int total) {
+ return '$enabled / $total개 레이어 사용 중';
+ }
+
+ @override
+ String get mapOsmSurface => '지표면';
+
+ @override
+ String get mapOsmParks => '공원';
+
+ @override
+ String get mapOsmLandUse => '토지 이용';
+
+ @override
+ String get mapOsmAirportAreas => '공항 지역';
+
+ @override
+ String get mapOsmWater => '수역';
+
+ @override
+ String get mapOsmRivers => '하천';
+
+ @override
+ String get mapOsmBoundaries => '경계';
+
+ @override
+ String get mapOsmBuildings => '건물';
+
+ @override
+ String get mapOsmRoads => '도로';
+
+ @override
+ String get mapOsmRoadNames => '도로명';
+
+ @override
+ String get mapOsmWaterNames => '수역 이름';
+
+ @override
+ String get mapOsmPeaks => '봉우리';
+
+ @override
+ String get mapOsmAirportNames => '공항 이름';
+
+ @override
+ String get mapOsmPlaceNames => '지명';
+
+ @override
+ String get mapOsmPoi => '관심 지점';
+
+ @override
+ String get mapOsmHouseNumbers => '건물 번호';
+
+ @override
+ String get mapOsmRestoreAll => '모두 복원';
+
+ @override
+ String get mapOsmSectionNatural => '자연 지형';
+
+ @override
+ String get mapOsmSectionRoadsAndBuildings => '도로 및 건물';
+
+ @override
+ String get mapOsmSectionLabelsAndPlaces => '레이블 및 장소';
+
@override
String get mapTownLabels => '읍면동 이름';
@@ -2291,10 +2392,10 @@ class AppLocalizationsKo extends AppLocalizations {
String get notifySetFailed => '설정을 저장하지 못했습니다. 다시 시도해 주세요.';
@override
- String get meshtasticDisconnect => 'Disconnect';
+ String get meshtasticDisconnect => '연결 해제';
@override
- String get meshtasticUndecoded => 'Not decrypted';
+ String get meshtasticUndecoded => '복호화되지 않음';
@override
String get notifyAnnouncement => '공지사항';
@@ -2830,6 +2931,50 @@ class AppLocalizationsKo extends AppLocalizations {
return '「$what」이(가) 거부되어 시스템이 다시 묻지 않습니다. 설정에서 허용해 주세요.';
}
+ @override
+ String get permissionGuideNotification => '시스템 설정에서 알림을 허용해 주세요.';
+
+ @override
+ String get permissionGuideForegroundLocation => '시스템 설정에서 정확한 위치를 허용해 주세요.';
+
+ @override
+ String permissionGuideBackgroundLocation(Object option) {
+ return '「$option」에서 「항상 허용」을 선택하세요.';
+ }
+
+ @override
+ String get permissionGuideBackgroundExecution =>
+ '시스템 설정에서 백그라운드 실행을 허용하여 알림이 중지되지 않게 하세요.';
+
+ @override
+ String get permissionGuideUnusedPause =>
+ '앱이 「사용 안 함」으로 표시되면 시스템 설정에서 「허용」을 선택하세요.';
+
+ @override
+ String get permissionGuideUnusedFreeSpace =>
+ '저장 공간 부족으로 일시중지된 경우 캐시를 지우고 다시 여세요.';
+
+ @override
+ String get permissionGuideUnusedRevoke => '앱 권한이 취소된 경우 시스템 설정에서 다시 허용하세요.';
+
+ @override
+ String get permissionGuideUnusedPlayProtect =>
+ 'Play 프로텍트가 앱을 일시중지한 경우 Google Play에서 상태를 확인하세요.';
+
+ @override
+ String permissionGuideVendorPower(Object vendor) {
+ return '「$vendor」의 절전 설정에서 이 앱을 「제한 없음」으로 설정하세요.';
+ }
+
+ @override
+ String get permissionStillRequired => '아직 필요합니다. 설정에서 활성화하세요.';
+
+ @override
+ String get permissionVerifyManually => '시스템 설정에서 이 권한이 활성화되어 있는지 직접 확인하세요.';
+
+ @override
+ String get permissionBackgroundLocationOption => '「항상 허용」';
+
@override
String get displayTextSize => '글자 크기';
@@ -2969,6 +3114,16 @@ class AppLocalizationsKo extends AppLocalizations {
@override
String get moreDumpDiagnosticsHint => '업로드한 뒤 링크를 복사합니다';
+ @override
+ String get dumpIncludeSensitive => '정확한 위치 포함';
+
+ @override
+ String get dumpIncludeSensitiveHint =>
+ '로그 및 백그라운드 위치의 좌표를 포함합니다. 선택하지 않으면 null로 대체됩니다';
+
+ @override
+ String get dumpUpload => '업로드';
+
@override
String get dumpUploaded => '업로드됨';
diff --git a/lib/l10n/gen/app_localizations_th.dart b/lib/l10n/gen/app_localizations_th.dart
index 53cf71e9c..b6afa23cc 100644
--- a/lib/l10n/gen/app_localizations_th.dart
+++ b/lib/l10n/gen/app_localizations_th.dart
@@ -56,7 +56,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get restroomTypeMale => 'ห้องน้ำชาย';
@override
- String get meshtasticLastReceived => 'Last received';
+ String get meshtasticLastReceived => 'รับล่าสุด';
@override
String get reportDetailSortByCounty => 'เรียงตามพื้นที่';
@@ -87,7 +87,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get homeRainTrendScattered => 'อาจมีฝนตกประปราย';
@override
- String get meshtasticUptime => 'Uptime';
+ String get meshtasticUptime => 'เวลาทำงาน';
@override
String get weatherRankingTempExtremes => 'ค่าสุดขั้วอุณหภูมิ';
@@ -99,7 +99,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get mapTerrainReliefHint => 'แสดงความนูนของภูมิประเทศบนแผนที่ฐาน';
@override
- String get meshtasticEmptyMessage => '(empty message)';
+ String get meshtasticEmptyMessage => '(ข้อความว่าง)';
@override
String get moreSectionRegion => 'พื้นที่';
@@ -111,7 +111,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get aedHoursSaturday => 'เวลาวันเสาร์';
@override
- String get moonPhaseNew => 'New moon';
+ String get moonPhaseNew => 'พระจันทร์ใหม่';
@override
String get notifySectionEew => 'การเตือนแผ่นดินไหวล่วงหน้า';
@@ -126,7 +126,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get mapTownLabelsHint => 'แสดงชื่อตำบลเมื่อขยายแผนที่';
@override
- String get commonCancel => 'Cancel';
+ String get commonCancel => 'ยกเลิก';
@override
String get notifyOptTsunamiWarning => 'เฉพาะการเตือนภัยสึนามิ';
@@ -166,7 +166,7 @@ class AppLocalizationsTh extends AppLocalizations {
@override
String get mapLayerStyleJmaTooltip =>
- 'Grayscale base, tinted below −40 °C to highlight cloud-top height';
+ 'ฐานเป็น grayscale แต่งสีต่ำกว่า −40 °C เพื่อเน้นความสูงยอดเมฆ';
@override
String get mapLayerRain => 'ปริมาณฝน';
@@ -220,7 +220,7 @@ class AppLocalizationsTh extends AppLocalizations {
@override
String get meshtasticExcludeMqttSubtitle =>
- 'Nodes bridged over the internet, not heard by radio';
+ 'โหนดที่เชื่อมผ่านอินเทอร์เน็ต ไม่ได้ยินผ่านวิทยุ';
@override
String get reportFilterIntensityInfoTitle => 'มาตรวัดความรุนแรงแบบใหม่/เก่า';
@@ -232,14 +232,14 @@ class AppLocalizationsTh extends AppLocalizations {
String get radarOverlayMenuTooltip => 'ตัวเลือกชั้นเรดาร์';
@override
- String get meshtasticNodes => 'Nodes';
+ String get meshtasticNodes => 'โหนด';
@override
- String get meshtasticSend => 'Send';
+ String get meshtasticSend => 'ส่ง';
@override
String get typhoonOverlayStormL7Tooltip =>
- 'Level-7 wind field + average circle (purple)';
+ 'สนามลมระดับ 7 + รัศมีเฉลี่ย (ม่วง)';
@override
String get aedType => 'ประเภท';
@@ -291,7 +291,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get skyTimeDusk => 'สนธยา';
@override
- String get meshtasticFirmware => 'Firmware';
+ String get meshtasticFirmware => 'เฟิร์มแวร์';
@override
String get reportFilterDateEndNote => 'วันสิ้นสุด: 24:00 ของวันนั้น(ไทเป)';
@@ -300,7 +300,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get reportFilterSortMagnitude => 'ขนาด';
@override
- String get meshtasticSilent => 'Silent';
+ String get meshtasticSilent => 'เงียบ';
@override
String get mapLayerCategoryEarthquake => 'แผ่นดินไหว';
@@ -334,7 +334,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get notifyOptTsunamiAll => 'ข่าวสารและการเตือนภัยสึนามิ';
@override
- String get meshtasticLayerOptions => 'Node options';
+ String get meshtasticLayerOptions => 'ตัวเลือกโหนด';
@override
String get onboardingAgreeContinue => 'ยอมรับและดำเนินการต่อ';
@@ -343,7 +343,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get commonRetry => 'ลองอีกครั้ง';
@override
- String get meshtasticNodeId => 'Node ID';
+ String get meshtasticNodeId => 'รหัสโหนด';
@override
String reportDetailNumbered(String number) {
@@ -351,7 +351,7 @@ class AppLocalizationsTh extends AppLocalizations {
}
@override
- String get typhoonOverlayStormBandSubtitle => 'With average circle';
+ String get typhoonOverlayStormBandSubtitle => 'พร้อมรัศมีเฉลี่ย';
@override
String get disasterMapOverlayRestroomTooltip => 'แสดงห้องน้ำสาธารณะ';
@@ -378,13 +378,13 @@ class AppLocalizationsTh extends AppLocalizations {
String get sponsorRestore => 'กู้คืนการซื้อ';
@override
- String get meshtasticChannelWorking => 'Setting up the DPIP channel…';
+ String get meshtasticChannelWorking => 'กำลังตั้งค่าช่อง DPIP…';
@override
- String get meshtasticRegionSwitch => 'Switch to TW';
+ String get meshtasticRegionSwitch => 'สลับเป็นภูมิภาค TW';
@override
- String get meshtasticTraffic => 'Traffic';
+ String get meshtasticTraffic => 'ปริมาณข้อมูล';
@override
String get mapLayerStyleBdTooltip =>
@@ -398,10 +398,10 @@ class AppLocalizationsTh extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentNight =>
- 'Night = transparent, the basemap shows';
+ 'กลางคืน = โปร่งใส เห็นแผนที่ฐาน';
@override
- String get meshtasticScanning => 'Scanning…';
+ String get meshtasticScanning => 'กำลังสแกน…';
@override
String regionSelectFull(int max) {
@@ -473,7 +473,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get navMore => 'เพิ่มเติม';
@override
- String get meshtasticDpipChannel => 'DPIP channel';
+ String get meshtasticDpipChannel => 'ช่อง DPIP';
@override
String get disasterMapOverlaySectionLayers => 'ชั้น';
@@ -485,7 +485,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get typhoonLabelNe => 'NE';
@override
- String get meshtasticCopied => 'Message copied';
+ String get meshtasticCopied => 'คัดลอกข้อความแล้ว';
@override
String get reportListEmpty => 'ไม่มีรายงานแผ่นดินไหว';
@@ -497,19 +497,19 @@ class AppLocalizationsTh extends AppLocalizations {
String get mapLayerSatelliteTruecolor => 'Himawari True Color';
@override
- String get typhoonOverlaySectionExtra => 'Overlays';
+ String get typhoonOverlaySectionExtra => 'เลเยอร์เสริม';
@override
String get eewSWave => 'คลื่น S';
@override
- String get meshtasticBusyTitle => 'Another app is using this radio';
+ String get meshtasticBusyTitle => 'แอปอื่นกำลังใช้วิทยุเครื่องนี้อยู่';
@override
String get restroomCategoryCultural => 'สถานที่ทางวัฒนธรรม';
@override
- String get typhoonLabelWind => 'Max. sustained wind near centre';
+ String get typhoonLabelWind => 'ลมแรงสุดต่อเนื่องใกล้ศูนย์กลาง';
@override
String get radarGlobalOutlineHint => 'กรอบนอกของทุกประเทศ';
@@ -521,7 +521,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get typhoonLegendCircle15 => 'วงพายุ (แรง)';
@override
- String get dataSectionAstronomy => 'Astronomy';
+ String get dataSectionAstronomy => 'ดาราศาสตร์';
@override
String get homeRainTrendLightSustained =>
@@ -531,10 +531,10 @@ class AppLocalizationsTh extends AppLocalizations {
String get commonError => 'เกิดข้อผิดพลาด';
@override
- String get moonPhaseWaningCrescent => 'Waning crescent';
+ String get moonPhaseWaningCrescent => 'จันทร์เสี้ยวข้างแรม';
@override
- String get meshtasticPower => 'Power';
+ String get meshtasticPower => 'พลังงาน';
@override
String get mapTimelineNow => 'ตอนนี้';
@@ -562,7 +562,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get notifyTitle => 'การแจ้งเตือน';
@override
- String get meshtasticTxPower => 'TX power';
+ String get meshtasticTxPower => 'กำลัง TX';
@override
String get restroomCategoryLabel => 'หมวดหมู่';
@@ -575,7 +575,7 @@ class AppLocalizationsTh extends AppLocalizations {
'DPIP มุ่งมั่นให้ข้อมูลการป้องกันภัยพิบัติแบบเรียลไทม์ โดยไม่มีโฆษณาหรือรูปแบบหารายได้อื่น การสนับสนุนของคุณช่วยให้เรารักษาเซิร์ฟเวอร์และพัฒนาต่อไปได้';
@override
- String get typhoonLabelStormAvg => 'Avg. radius of Beaufort 10 winds';
+ String get typhoonLabelStormAvg => 'รัศมีเฉลี่ยลมโบฟอร์ต 10';
@override
String get restroomCategoryCommercial => 'สถานประกอบการพาณิชย์';
@@ -609,10 +609,10 @@ class AppLocalizationsTh extends AppLocalizations {
String get restroomTypeUnspecified => 'ไม่ระบุ';
@override
- String get typhoonOverlayProbabilityHint => 'Hides the forecast cone';
+ String get typhoonOverlayProbabilityHint => 'ซ่อนกรวยคาดการณ์';
@override
- String get mapLayerSatelliteGlobalOutline => 'Country border';
+ String get mapLayerSatelliteGlobalOutline => 'เส้นขอบประเทศ';
@override
String get mapNavTemperature => 'อุณหภูมิ';
@@ -647,7 +647,7 @@ class AppLocalizationsTh extends AppLocalizations {
@override
String get typhoonOverlayWeatherRadarTooltip =>
- 'Radar echo closest to the typhoon bulletin time';
+ 'เรดาร์สะท้อนที่ใกล้เวลารายงานพายุไต้ฝุ่นที่สุด';
@override
String get onboardingPermLocationDesc => 'ส่งการเตือนภัยตามตำแหน่งที่คุณอยู่';
@@ -659,13 +659,13 @@ class AppLocalizationsTh extends AppLocalizations {
String get homeActiveEventsEmpty => 'ไม่มีเหตุการณ์ที่ยังมีผล';
@override
- String get typhoonLabelPosition => 'Centre location';
+ String get typhoonLabelPosition => 'ตำแหน่งศูนย์กลาง';
@override
String get weatherRankingBy => 'เรียง';
@override
- String get typhoonIntensityMild => 'Mild typhoon';
+ String get typhoonIntensityMild => 'พายุไต้ฝุ่นอ่อน';
@override
String get windForecastGlobalOutlineHint => 'กรอบนอกของทุกประเทศ';
@@ -683,10 +683,10 @@ class AppLocalizationsTh extends AppLocalizations {
String get restroomCategoryReligious => 'สถานที่ทางศาสนา';
@override
- String get meshtasticRole => 'Role';
+ String get meshtasticRole => 'บทบาท';
@override
- String get mapLayerSatelliteCloudCloudy => 'Cloudy';
+ String get mapLayerSatelliteCloudCloudy => 'มีเมฆ';
@override
String get skyTimeSunrise => 'พระอาทิตย์ขึ้น';
@@ -695,7 +695,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get meshtasticJumpToLatest => 'ไปที่ล่าสุด';
@override
- String get meshtasticNoMessages => 'No messages yet';
+ String get meshtasticNoMessages => 'ยังไม่มีข้อความ';
@override
String get onboardingPermNotifyDesc =>
@@ -705,7 +705,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get radarTownOutline => 'เส้นแบ่งเขตอำเภอ';
@override
- String get mapLayerStyleSection => 'Colour style';
+ String get mapLayerStyleSection => 'สไตล์สี';
@override
String get disasterMapOverlayMenuTooltip => 'ชั้นแผนที่ป้องกันภัย';
@@ -714,7 +714,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get moreGooglePlay => 'Google Play';
@override
- String get meshtasticOnline => 'Heard recently';
+ String get meshtasticOnline => 'เพิ่งได้ยิน';
@override
String get typhoonLabelSw => 'SW';
@@ -729,7 +729,7 @@ class AppLocalizationsTh extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentClear =>
- 'Clear sky = transparent, the basemap shows';
+ 'ท้องฟ้าใส = โปร่งใส เห็นแผนที่ฐาน';
@override
String get mapOverlaySectionReference => 'เลเยอร์อ้างอิง';
@@ -763,7 +763,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get eewArrived => 'มาถึงแล้ว';
@override
- String get meshtasticNoDevices => 'No Meshtastic devices found';
+ String get meshtasticNoDevices => 'ไม่พบอุปกรณ์ Meshtastic';
@override
String get mapLayerCategoryLife => 'ชีวิตประจำวัน';
@@ -772,10 +772,10 @@ class AppLocalizationsTh extends AppLocalizations {
String get reportFilterSortIntensity => 'ความเข้ม';
@override
- String get meshtasticStateDisconnected => 'Disconnected';
+ String get meshtasticStateDisconnected => 'ตัดการเชื่อมต่อแล้ว';
@override
- String get typhoonIntensityIntense => 'Intense typhoon';
+ String get typhoonIntensityIntense => 'พายุไต้ฝุ่นรุนแรง';
@override
String get mapLayerOrderTitle => 'จัดเรียงเลเยอร์';
@@ -784,7 +784,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get dpmYes => 'ใช่';
@override
- String get meshtasticNoHistory => 'Not enough history yet';
+ String get meshtasticNoHistory => 'ประวัติยังไม่พอ';
@override
String get reportDetailLocalIntensityUnavailable => 'ไม่มีข้อมูลความเข้ม';
@@ -811,10 +811,10 @@ class AppLocalizationsTh extends AppLocalizations {
String get mapLayerSatelliteMndwi => 'Himawari MNDWI';
@override
- String get typhoonOverlaySectionStorm => 'Storm wind';
+ String get typhoonOverlaySectionStorm => 'ลมพายุ';
@override
- String get moonPhaseFull => 'Full moon';
+ String get moonPhaseFull => 'พระจันทร์เต็มดวง';
@override
String meshtasticBinaryPayload(String size) {
@@ -822,14 +822,14 @@ class AppLocalizationsTh extends AppLocalizations {
}
@override
- String get moonPhaseWaningGibbous => 'Waning gibbous';
+ String get moonPhaseWaningGibbous => 'จันทร์นูนข้างแรม';
@override
String get reportFilterIntensityInfoModernTitle => 'แบบใหม่ (ตั้งแต่ 2020)';
@override
String typhoonDataTime(String time) {
- return 'Data time\n$time';
+ return 'เวลาข้อมูล\n$time';
}
@override
@@ -839,7 +839,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get moreSectionAbout => 'เกี่ยวกับ';
@override
- String get meshtasticSelectDevice => 'Select a radio';
+ String get meshtasticSelectDevice => 'เลือกวิทยุ';
@override
String get onboardingIntroBody =>
@@ -852,19 +852,19 @@ class AppLocalizationsTh extends AppLocalizations {
String get reportDetailImage => 'ภาพรายงานแผ่นดินไหว';
@override
- String get meshtasticStateConfiguring => 'Configuring…';
+ String get meshtasticStateConfiguring => 'กำลังกำหนดค่า…';
@override
- String get typhoonLabelGaleAvg => 'Avg. radius of Beaufort 7 winds';
+ String get typhoonLabelGaleAvg => 'รัศมีเฉลี่ยลมโบฟอร์ต 7';
@override
String get onboardingPermNotify => 'การแจ้งเตือน';
@override
- String get meshtasticClearMessages => 'Clear messages';
+ String get meshtasticClearMessages => 'ล้างข้อความ';
@override
- String get meshtasticNotifyMessages => 'Notify on new messages';
+ String get meshtasticNotifyMessages => 'แจ้งเตือนข้อความใหม่';
@override
String get defaultMapLayerSettings => 'ชั้นแผนที่เริ่มต้น';
@@ -942,7 +942,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get mapTimelineFuture => 'อนาคต';
@override
- String get typhoonLegendCircleAvg => 'Average circle';
+ String get typhoonLegendCircleAvg => 'รัศมีเฉลี่ย';
@override
String reportFilterDepthKm(String depth) {
@@ -961,7 +961,7 @@ class AppLocalizationsTh extends AppLocalizations {
}
@override
- String get typhoonLabelGust => 'Peak gust';
+ String get typhoonLabelGust => 'ลมกระโชกสูงสุด';
@override
String get mapAppGoogleMaps => 'Google Maps';
@@ -979,7 +979,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get skyTimeGolden => 'ช่วงเวลาทอง';
@override
- String get moonAge => 'Age';
+ String get moonAge => 'อายุจันทร์';
@override
String get meshtasticRadioSettings => 'LoRa';
@@ -994,7 +994,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get mapLayers => 'ชั้นข้อมูล';
@override
- String get meshtasticHardware => 'Hardware';
+ String get meshtasticHardware => 'ฮาร์ดแวร์';
@override
String get languageSettings => 'ภาษา';
@@ -1008,7 +1008,7 @@ class AppLocalizationsTh extends AppLocalizations {
}
@override
- String get typhoonOverlayWeatherHint => 'Aligned to bulletin time';
+ String get typhoonOverlayWeatherHint => 'จัดให้ตรงเวลารายงาน';
@override
String get skyTimeDawn => 'รุ่งอรุณ';
@@ -1017,7 +1017,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get skyTimeAfternoon => 'ตอนบ่าย';
@override
- String get meshtasticLastHeard => 'Last heard';
+ String get meshtasticLastHeard => 'ได้ยินล่าสุด';
@override
String get typhoonWarningTitle => 'ประกาศเตือนไต้ฝุ่น';
@@ -1068,10 +1068,10 @@ class AppLocalizationsTh extends AppLocalizations {
@override
String get typhoonOverlayStormL10Tooltip =>
- 'Level-10 wind field + average circle (yellow)';
+ 'สนามลมระดับ 10 + รัศมีเฉลี่ย (เหลือง)';
@override
- String get moonPhaseWaxingGibbous => 'Waxing gibbous';
+ String get moonPhaseWaxingGibbous => 'จันทร์นูนข้างขึ้น';
@override
String get reportDetailTitle => 'รายงานแผ่นดินไหว';
@@ -1085,10 +1085,10 @@ class AppLocalizationsTh extends AppLocalizations {
}
@override
- String get meshtasticNoNodes => 'No nodes heard yet';
+ String get meshtasticNoNodes => 'ยังไม่พบโหนด';
@override
- String get meshtasticViaMqtt => 'Via MQTT (internet)';
+ String get meshtasticViaMqtt => 'ผ่าน MQTT (อินเทอร์เน็ต)';
@override
String get radarCountyOutline => 'เส้นแบ่งเขตจังหวัด';
@@ -1106,11 +1106,11 @@ class AppLocalizationsTh extends AppLocalizations {
String get changelogCurrentVersion => 'ปัจจุบัน';
@override
- String get typhoonLabelPressure => 'Central pressure';
+ String get typhoonLabelPressure => 'ความกดอากาศศูนย์กลาง';
@override
String get typhoonOverlayForecastCalloutsTooltip =>
- 'Show forecast-point detail cards when zoomed in';
+ 'แสดงการ์ดรายละเอียดจุดคาดการณ์เมื่อซูมเข้า';
@override
String get aedOpenRemark => 'หมายเหตุเวลาเปิด';
@@ -1120,7 +1120,7 @@ class AppLocalizationsTh extends AppLocalizations {
'เพื่อให้ DPIP แจ้งเตือนคุณได้ในทันทีที่เกิดภัยพิบัติ โปรดอนุญาตสิทธิ์ต่อไปนี้ คุณสามารถเปลี่ยนแปลงได้ทุกเมื่อในการตั้งค่าระบบ';
@override
- String get typhoonOverlaySectionWeather => 'Weather underlay';
+ String get typhoonOverlaySectionWeather => 'พื้นหลังสภาพอากาศ';
@override
String get notifyOptWeatherLocal => 'เฉพาะตำแหน่งปัจจุบัน';
@@ -1129,7 +1129,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get mapNavRain => 'ฝน';
@override
- String get moonDays => 'days';
+ String get moonDays => 'วัน';
@override
String mapLegendUnit(String unit) {
@@ -1140,7 +1140,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get weatherModeClear => 'ท้องฟ้าแจ่มใส';
@override
- String get meshtasticRadio => 'Radio';
+ String get meshtasticRadio => 'วิทยุ';
@override
String get commonEmpty => 'ไม่มีข้อมูล';
@@ -1149,10 +1149,10 @@ class AppLocalizationsTh extends AppLocalizations {
String get mapLayerSatelliteB01 => 'Himawari Blue (B01)';
@override
- String get meshtasticExternalPower => 'External power';
+ String get meshtasticExternalPower => 'พลังงานภายนอก';
@override
- String get moonPhaseLastQuarter => 'Last quarter';
+ String get moonPhaseLastQuarter => 'จันทร์กึ่งดวงข้างแรม';
@override
String get reportFilterOrderAsc => 'น้อย→มาก';
@@ -1179,19 +1179,19 @@ class AppLocalizationsTh extends AppLocalizations {
String get restroomGradeExcellent => 'ดีเยี่ยม';
@override
- String get meshtasticLastSent => 'Last sent';
+ String get meshtasticLastSent => 'ส่งล่าสุด';
@override
- String get meshtasticName => 'Name';
+ String get meshtasticName => 'ชื่อ';
@override
- String get meshtasticScan => 'Scan';
+ String get meshtasticScan => 'สแกน';
@override
String get mapLayerCategoryForecast => 'การพยากรณ์เชิงตัวเลข';
@override
- String get meshtasticChannelFailed => 'Couldn\'t set up the DPIP channel';
+ String get meshtasticChannelFailed => 'ตั้งค่าช่อง DPIP ไม่สำเร็จ';
@override
String get themeSystem => 'ระบบ';
@@ -1211,7 +1211,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get weatherPrecipitation => 'ปริมาณน้ำฝน';
@override
- String get moonNextFullMoon => 'Next full moon';
+ String get moonNextFullMoon => 'พระจันทร์เต็มดวงครั้งถัดไป';
@override
String get dpmSheetEmpty => 'แตะเครื่องหมายบนแผนที่เพื่อดูรายละเอียด';
@@ -1240,7 +1240,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get typhoonLabelNw => 'NW';
@override
- String get moonPhaseWaxingCrescent => 'Waxing crescent';
+ String get moonPhaseWaxingCrescent => 'จันทร์เสี้ยวข้างขึ้น';
@override
String get restroomCategoryLeisure => 'สถานที่พักผ่อนหย่อนใจ';
@@ -1252,23 +1252,22 @@ class AppLocalizationsTh extends AppLocalizations {
String get aedCategory => 'หมวดหมู่';
@override
- String get meshtasticChannels => 'Channels';
+ String get meshtasticChannels => 'ช่อง';
@override
String get monitorWaiting => 'กำลังรอข้อมูล…';
@override
- String get typhoonOverlayForecastCallouts => 'Forecast tooltips';
+ String get typhoonOverlayForecastCallouts => 'คำอธิบายจุดคาดการณ์';
@override
String get reportDetailEpicenter => 'พิกัดศูนย์กลาง';
@override
- String get meshtasticVoltage => 'Voltage';
+ String get meshtasticVoltage => 'แรงดันไฟฟ้า';
@override
- String get mapLayerMeshtasticSubtitle =>
- 'LoRa mesh nodes heard by your radio';
+ String get mapLayerMeshtasticSubtitle => 'โหนดเมช LoRa ที่วิทยุได้ยิน';
@override
String get mapLayerWind => 'ลม';
@@ -1306,7 +1305,7 @@ class AppLocalizationsTh extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentZero =>
- 'Zero difference = transparent (no signal)';
+ 'ค่าต่างเป็นศูนย์ = โปร่งใส (ไม่มีสัญญาณ)';
@override
String get shelterIndoorLabel => 'การอพยพในอาคาร';
@@ -1318,7 +1317,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get reportFilterSortTime => 'เวลา';
@override
- String get mapLayerSatelliteCloudProbablyClear => 'Probably clear';
+ String get mapLayerSatelliteCloudProbablyClear => 'น่าจะปลอดโปร่ง';
@override
String get weatherModeThunderstorm => 'พายุฝนฟ้าคะนอง';
@@ -1330,7 +1329,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get reportFilterIntensityInfoLegacyTitle => 'แบบเก่า (ก่อน 2020)';
@override
- String get typhoonLabelSpeed => 'Past movement speed';
+ String get typhoonLabelSpeed => 'ความเร็วเคลื่อนที่';
@override
String mapAppOpenFailed(String app) {
@@ -1338,10 +1337,10 @@ class AppLocalizationsTh extends AppLocalizations {
}
@override
- String get mapLayerSatelliteRgbComposite => 'RGB composite (JMA recipe)';
+ String get mapLayerSatelliteRgbComposite => 'RGB composite (สูตร JMA)';
@override
- String get meshtasticReceived => 'Received';
+ String get meshtasticReceived => 'รับแล้ว';
@override
String get weatherRankingExtremeLow => 'ต่ำสุดวันนี้';
@@ -1350,7 +1349,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get mapLayerSatelliteB10 => 'Himawari Lower Water Vapour (B10)';
@override
- String get mapLayerSatelliteCloudProbablyCloudy => 'Probably cloudy';
+ String get mapLayerSatelliteCloudProbablyCloudy => 'น่าจะมีเมฆ';
@override
String get mapLayerSatelliteTransparentNoWater =>
@@ -1360,10 +1359,10 @@ class AppLocalizationsTh extends AppLocalizations {
String get shelterCategoryLabel => 'ประเภทภัยพิบัติ';
@override
- String get meshtasticStateConnecting => 'Connecting…';
+ String get meshtasticStateConnecting => 'กำลังเชื่อมต่อ…';
@override
- String get moonTitle => 'Moon';
+ String get moonTitle => 'ดวงจันทร์';
@override
String get weatherRankingGust => 'ลมกระโชก';
@@ -1378,7 +1377,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get notifySectionWeather => 'สภาพอากาศ';
@override
- String get meshtasticPreset => 'Modem preset';
+ String get meshtasticPreset => 'โหมดโมเด็ม';
@override
String get dataSectionSeismic => 'แผ่นดินไหว';
@@ -1405,13 +1404,13 @@ class AppLocalizationsTh extends AppLocalizations {
String get regionCurrent => 'ตำแหน่งปัจจุบัน';
@override
- String get meshtasticNotConnected => 'Not connected to a radio';
+ String get meshtasticNotConnected => 'ยังไม่ได้เชื่อมต่อกับวิทยุ';
@override
String get weatherModeSnow => 'หิมะตก';
@override
- String get mapLayerMeshtastic => 'Meshtastic nodes';
+ String get mapLayerMeshtastic => 'โหนด Meshtastic';
@override
String get moreDeveloper => 'ข้อมูลดีบัก';
@@ -1420,7 +1419,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get mapLayerSatelliteB14 => 'Himawari Longwave Infrared (B14)';
@override
- String get meshtasticChannelUse => 'Channel use';
+ String get meshtasticChannelUse => 'การใช้ช่อง';
@override
String get mapNavLightning => 'ฟ้าผ่า';
@@ -1444,7 +1443,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get dpmOpenInMaps => 'เปิดในแผนที่';
@override
- String get meshtasticNotifyNodes => 'Notify on new nodes';
+ String get meshtasticNotifyNodes => 'แจ้งเตือนโหนดใหม่';
@override
String get onboardingPermCriticalDesc =>
@@ -1452,10 +1451,10 @@ class AppLocalizationsTh extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentWarm =>
- 'Clear sky (warm end) = transparent, the basemap shows';
+ 'ท้องฟ้าใส (ปลายอุ่น) = โปร่งใส เห็นแผนที่ฐาน';
@override
- String get meshtasticSent => 'Sent';
+ String get meshtasticSent => 'ส่งแล้ว';
@override
String get homeForecastTitle => 'พยากรณ์ 24 ชั่วโมง';
@@ -1465,7 +1464,7 @@ class AppLocalizationsTh extends AppLocalizations {
@override
String meshtasticExcludeMqttHidden(int count) {
- return '$count hidden';
+ return 'ซ่อน $count รายการ';
}
@override
@@ -1481,13 +1480,13 @@ class AppLocalizationsTh extends AppLocalizations {
String get reportListToday => 'วันนี้';
@override
- String get meshtasticTapNode => 'Tap a node for details';
+ String get meshtasticTapNode => 'แตะโหนดเพื่อดูรายละเอียด';
@override
String get commonLoading => 'กำลังโหลด…';
@override
- String get typhoonIntensityModerate => 'Moderate typhoon';
+ String get typhoonIntensityModerate => 'พายุไต้ฝุ่นปานกลาง';
@override
String get mapLayerSatelliteAsh => 'Himawari Ash';
@@ -1499,14 +1498,14 @@ class AppLocalizationsTh extends AppLocalizations {
String get mapLayerCategorySatellite => 'ดาวเทียม';
@override
- String get meshtasticChannelReady => 'DPIP channel ready';
+ String get meshtasticChannelReady => 'ช่อง DPIP พร้อมแล้ว';
@override
String get mapLayerSatelliteNightmicrophysics =>
'Himawari Night Microphysics';
@override
- String get typhoonIntensityTd => 'Tropical depression';
+ String get typhoonIntensityTd => 'ดีเปรสชันเขตร้อน';
@override
String get reportFilterDate => 'วันที่';
@@ -1581,7 +1580,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get mapLayerSatelliteBtdSo2 => 'Himawari SO₂ / Cloud Phase';
@override
- String get meshtasticStateError => 'Error';
+ String get meshtasticStateError => 'ข้อผิดพลาด';
@override
String get weatherModeOvercast => 'ฟ้าปิด';
@@ -1591,7 +1590,7 @@ class AppLocalizationsTh extends AppLocalizations {
@override
String get typhoonOverlayWarningTooltip =>
- 'Highlight counties under a typhoon warning';
+ 'ไฮไลต์จังหวัดที่อยู่ใต้คำเตือนพายุไต้ฝุ่น';
@override
String get reportFilterDatePick => 'เลือกวันที่';
@@ -1606,13 +1605,13 @@ class AppLocalizationsTh extends AppLocalizations {
String get shelterOutdoorLabel => 'การอพยพกลางแจ้ง';
@override
- String get meshtasticStateConnected => 'Connected';
+ String get meshtasticStateConnected => 'เชื่อมต่อแล้ว';
@override
String get mapNavRadar => 'เรดาร์';
@override
- String get mapLayerSatelliteCloudClear => 'Clear';
+ String get mapLayerSatelliteCloudClear => 'ปลอดโปร่ง';
@override
String eewSummary(String magnitude, String depth) {
@@ -1625,7 +1624,7 @@ class AppLocalizationsTh extends AppLocalizations {
@override
String get typhoonOverlayWeatherNoneTooltip =>
- 'No radar or infrared underlay';
+ 'ไม่มีพื้นหลังเรดาร์หรืออินฟราเรด';
@override
String get radarCountyOutlineHint => 'วาดทับภาพเอคโค';
@@ -1637,13 +1636,13 @@ class AppLocalizationsTh extends AppLocalizations {
String get homeRainTrendTitle => 'ฝนชั่วโมงถัดไป';
@override
- String get moonPhaseFirstQuarter => 'First quarter';
+ String get moonPhaseFirstQuarter => 'จันทร์กึ่งดวงข้างขึ้น';
@override
String get mapLayerCategoryTyphoon => 'พายุไต้ฝุ่น';
@override
- String get meshtasticUtilization => 'Airtime (24h)';
+ String get meshtasticUtilization => 'เวลาออกอากาศ (24 ชม.)';
@override
String get restroomTypeMixed => 'ห้องน้ำรวม';
@@ -1661,7 +1660,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get mapLayerSatelliteBtdWvirw => 'Himawari Overshooting Top';
@override
- String get meshtasticReadingAge => 'Reading taken';
+ String get meshtasticReadingAge => 'เวลาวัดค่า';
@override
String get mapAppCallFailed => 'อุปกรณ์นี้ไม่สามารถโทรออกได้';
@@ -1682,7 +1681,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get reportDetailLocalFelt => 'แผ่นดินไหวรู้สึกได้เฉพาะพื้นที่';
@override
- String get meshtasticDevice => 'Device';
+ String get meshtasticDevice => 'อุปกรณ์';
@override
String get onboardingGrant => 'อนุญาต';
@@ -1730,7 +1729,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get reportListEmptyFiltered => 'ไม่มีรายงานที่ตรงกับเงื่อนไข';
@override
- String get meshtasticExcludeMqtt => 'Hide MQTT nodes';
+ String get meshtasticExcludeMqtt => 'ซ่อนโหนด MQTT';
@override
String get mapNavTyphoon => 'ไต้ฝุ่น';
@@ -1768,13 +1767,13 @@ class AppLocalizationsTh extends AppLocalizations {
String get navHome => 'หน้าแรก';
@override
- String get meshtasticRegionLabel => 'Region';
+ String get meshtasticRegionLabel => 'ภูมิภาค';
@override
String get mapLayerSatelliteCloudtop => 'Himawari Cloud Top Temperature';
@override
- String get moonTimelineCaption => 'Phase';
+ String get moonTimelineCaption => 'ข้างขึ้นข้างแรม';
@override
String get openSourceLicenses => 'ใบอนุญาตโอเพนซอร์ส';
@@ -1794,7 +1793,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get radarScanRange => 'แสดงขอบเขตการสแกน';
@override
- String get meshtasticHopLimit => 'Hop limit';
+ String get meshtasticHopLimit => 'จำนวนฮอปสูงสุด';
@override
String get weatherRankingExtremeHigh => 'สูงสุดวันนี้';
@@ -1809,7 +1808,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get mapLayerSatelliteNaturalcolor => 'Himawari Natural Color';
@override
- String get meshtasticAirtime => 'Air time (TX)';
+ String get meshtasticAirtime => 'เวลาออกอากาศ (TX)';
@override
String shelterCapacityValue(int n) {
@@ -1822,7 +1821,7 @@ class AppLocalizationsTh extends AppLocalizations {
}
@override
- String get meshtasticSendHint => 'Message to broadcast';
+ String get meshtasticSendHint => 'ข้อความที่จะส่ง';
@override
String monitorDelay(String value) {
@@ -1836,7 +1835,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get mapLayerSatelliteB08 => 'Himawari Upper Water Vapour (B08)';
@override
- String get meshtasticReconnecting => 'Reconnecting…';
+ String get meshtasticReconnecting => 'กำลังเชื่อมต่อใหม่…';
@override
String get radarTownOutlineSubtitle =>
@@ -1844,14 +1843,14 @@ class AppLocalizationsTh extends AppLocalizations {
@override
String get typhoonOverlayWeatherSatelliteTooltip =>
- 'Infrared closest to the typhoon bulletin time';
+ 'อินฟราเรดที่ใกล้เวลารายงานพายุไต้ฝุ่นที่สุด';
@override
String get radarScanRangeHint => 'นอกกรอบคือไม่ได้ตรวจวัด';
@override
String typhoonPickerTd(String no) {
- return 'Tropical depression TD $no';
+ return 'ดีเปรสชันเขตร้อน TD $no';
}
@override
@@ -1874,7 +1873,7 @@ class AppLocalizationsTh extends AppLocalizations {
'บริการระบุตำแหน่งถูกปิด — ไม่สามารถส่งการเตือนภัยเฉพาะพื้นที่ของคุณได้';
@override
- String get mapLayerStyleTooltip => 'Colour style';
+ String get mapLayerStyleTooltip => 'สไตล์สี';
@override
String lightningLegendCg(int minutes) {
@@ -2001,49 +2000,49 @@ class AppLocalizationsTh extends AppLocalizations {
String get endpointServiceRts => 'RTS';
@override
- String get endpointServiceRadar => 'Radar';
+ String get endpointServiceRadar => 'เรดาร์';
@override
- String get endpointServiceSatellite => 'Satellite';
+ String get endpointServiceSatellite => 'ดาวเทียม';
@override
String get endpointServiceQpesums => 'QPE';
@override
- String get endpointServiceWind => 'Wind';
+ String get endpointServiceWind => 'ลม';
@override
- String get endpointServiceDpm => 'Disaster points';
+ String get endpointServiceDpm => 'จุดภัยพิบัติ';
@override
- String get endpointServiceWeather => 'Weather';
+ String get endpointServiceWeather => 'สภาพอากาศ';
@override
- String get endpointServiceRain => 'Rain';
+ String get endpointServiceRain => 'ฝน';
@override
- String get endpointServiceLightning => 'Lightning';
+ String get endpointServiceLightning => 'ฟ้าผ่า';
@override
- String get endpointServiceTyphoon => 'Typhoon';
+ String get endpointServiceTyphoon => 'พายุไต้ฝุ่น';
@override
- String get endpointServiceReport => 'EQ reports';
+ String get endpointServiceReport => 'รายงานแผ่นดินไหว';
@override
- String get endpointServiceTremStation => 'Tremor station';
+ String get endpointServiceTremStation => 'สถานีวัดแรงสั่นสะเทือน';
@override
- String get endpointServiceEvent => 'Events';
+ String get endpointServiceEvent => 'เหตุการณ์';
@override
- String get endpointServiceLocation => 'Location';
+ String get endpointServiceLocation => 'ตำแหน่ง';
@override
- String get endpointServiceNotify => 'Notifications';
+ String get endpointServiceNotify => 'การแจ้งเตือน';
@override
- String get endpointServiceOther => 'Other';
+ String get endpointServiceOther => 'อื่น ๆ';
@override
String get feedConnecting => 'กำลังเชื่อมต่อ…';
@@ -2067,17 +2066,16 @@ class AppLocalizationsTh extends AppLocalizations {
@override
String get meshtasticBusyBody =>
- 'Disconnect it in the other Meshtastic app first. Two apps on one radio take each other\'s messages, so some will go missing.';
+ 'ตัดการเชื่อมต่อวิทยุในแอป Meshtastic อื่นก่อน วิทยุเครื่องเดียวที่ใช้สองแอปจะแย่งข้อความกัน บางข้อความอาจหายไป';
@override
- String get meshtasticChannelNoSlot =>
- 'No free channel slot — free one on the radio';
+ String get meshtasticChannelNoSlot => 'ไม่มีช่องว่าง — ปล่อยช่องหนึ่งบนวิทยุ';
@override
String get restroomCategoryTransport => 'การคมนาคม';
@override
- String get meshtasticBattery => 'Battery';
+ String get meshtasticBattery => 'แบตเตอรี่';
@override
String get meshtasticDistance => 'ระยะทาง';
@@ -2089,14 +2087,14 @@ class AppLocalizationsTh extends AppLocalizations {
String get meshtasticBatteryTrend => 'แนวโน้มแบตเตอรี่';
@override
- String get typhoonOverlayMenuTooltip => 'Typhoon overlay options';
+ String get typhoonOverlayMenuTooltip => 'ตัวเลือกเลเยอร์พายุไต้ฝุ่น';
@override
String get mapLayerSatelliteBtdOzone => 'Himawari Tropopause';
@override
String meshtasticRegionMismatch(String region) {
- return 'Radio region is $region — DPIP needs TW';
+ return 'ภูมิภาคของวิทยุคือ $region — DPIP ต้องการ TW';
}
@override
@@ -2114,7 +2112,7 @@ class AppLocalizationsTh extends AppLocalizations {
}
@override
- String get mapLayerStyleGrayTooltip => 'JMA grayscale — colder is whiter';
+ String get mapLayerStyleGrayTooltip => 'JMA grayscale — ยิ่งเย็นยิ่งขาว';
@override
String get moreAnnouncements => 'ประกาศ';
@@ -2126,10 +2124,16 @@ class AppLocalizationsTh extends AppLocalizations {
String get moreVersionStable => 'เวอร์ชันเต็ม';
@override
- String get moreVersionNotes => 'เวอร์ชันปัจจุบัน';
+ String get moreVersionNotes => 'อัปเดตนี้';
@override
- String get releaseHighlightsTitle => 'สิ่งที่เปลี่ยนแปลง';
+ String get moreVersionNotesHighlightsSubtitle =>
+ 'สิ่งที่เปลี่ยนไปในเวอร์ชันนี้';
+
+ @override
+ String releaseHighlightsTitle(Object train) {
+ return '$train สรุปสำคัญ';
+ }
@override
String get releaseHighlightsTabNormal => 'สำหรับผู้ใช้';
@@ -2173,16 +2177,16 @@ class AppLocalizationsTh extends AppLocalizations {
'ระดับ 0–4, 5−, 5+, 6−, 6+, 7 แถบตัวกรองใช้แบบใหม่ เหตุการณ์เก่าในรายการยังแสดงป้ายแบบเก่า';
@override
- String get typhoonOverlayWeatherNone => 'None';
+ String get typhoonOverlayWeatherNone => 'ไม่มี';
@override
- String get mapLayerStyleGray => 'Grayscale (JMA)';
+ String get mapLayerStyleGray => 'ระดับสีเทา (JMA)';
@override
String get weatherModeAuto => 'อัตโนมัติ';
@override
- String get typhoonLabelProbCircle => '70% probability circle';
+ String get typhoonLabelProbCircle => 'วงกลมความน่าจะเป็น 70%';
@override
String get notifyOptAll => 'รับทั้งหมด';
@@ -2194,7 +2198,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get mapLayerSatelliteB07 => 'Himawari Shortwave Infrared (B07)';
@override
- String get typhoonLabelDirection => 'Past movement direction';
+ String get typhoonLabelDirection => 'ทิศทางการเคลื่อนที่';
@override
String get regionManageTitle => 'พื้นที่ที่ใช้บ่อย';
@@ -2214,13 +2218,13 @@ class AppLocalizationsTh extends AppLocalizations {
String get onboardingPermsTitle => 'การอนุญาตสิทธิ์';
@override
- String get mapLayerStyleJma => 'Cloud-top enhancement (JMA)';
+ String get mapLayerStyleJma => 'การเพิ่มคอนทราสต์กลุ่มเมฆ (JMA)';
@override
String get rainInterval10m => '10 นาที';
@override
- String get meshtasticConnectAnyway => 'Connect anyway';
+ String get meshtasticConnectAnyway => 'เชื่อมต่อต่อไป';
@override
String reportListDayCount(int count) {
@@ -2232,7 +2236,7 @@ class AppLocalizationsTh extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentReflectance =>
- 'Low reflectance / night = transparent, the basemap shows';
+ 'สะท้อนต่ำ / กลางคืน = โปร่งใส เห็นแผนที่ฐาน';
@override
String chartHourLabel(int hour) {
@@ -2244,7 +2248,7 @@ class AppLocalizationsTh extends AppLocalizations {
@override
String get typhoonOverlayProbabilityTooltip =>
- 'Show strike probability (hides the forecast cone)';
+ 'แสดงความน่าจะเป็นถูกพายุโจมตี (ซ่อนกรวยคาดการณ์)';
@override
String get mapLayerSatelliteNdwi => 'Himawari NDWI';
@@ -2265,7 +2269,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get mapLayerCategoryRadar => 'เรดาร์';
@override
- String get meshtasticShortName => 'Short name';
+ String get meshtasticShortName => 'ชื่อสั้น';
@override
String get mapLayerSatelliteAirmass => 'Himawari Airmass';
@@ -2292,7 +2296,7 @@ class AppLocalizationsTh extends AppLocalizations {
@override
String get meshtasticRegionConfirm =>
- 'Switch this radio to the TW region? It restarts and disconnects for a moment, and every other channel on it moves too.';
+ 'สลับวิทยุนี้เป็นภูมิภาค TW หรือไม่ วิทยุจะรีสตาร์ทและตัดการเชื่อมต่อชั่วครู่ และทุกช่องอื่นจะย้ายไปด้วย';
@override
String get dataEarthquakeSubtitle => 'รายงานแผ่นดินไหว';
@@ -2309,6 +2313,113 @@ class AppLocalizationsTh extends AppLocalizations {
@override
String get onboardingTermsTitle => 'ข้อกำหนดการให้บริการ';
+ @override
+ String get mapOsmOverlay => 'แผนที่แบบละเอียด';
+
+ @override
+ String get mapOsmOverlayHint => 'แสดงถนน อาคาร และชื่อสถานที่อย่างละเอียด';
+
+ @override
+ String get mapOsmDetails => 'รายละเอียดเลเยอร์';
+
+ @override
+ String get moreDataSources => 'แหล่งข้อมูล';
+
+ @override
+ String get dataSourceTremNet => '探索智慧科技有限公司 — TREM-Net';
+
+ @override
+ String get dataSourceCwa => '交通部中央氣象署 (CWA)';
+
+ @override
+ String get dataSourceJma => '気象庁 (JMA)';
+
+ @override
+ String get dataSourceNcdr => '國家災害防救科技中心 (NCDR)';
+
+ @override
+ String get dataSourceEcmwf =>
+ 'European Centre for Medium-Range Weather Forecasts (ECMWF)';
+
+ @override
+ String get dataSourceNoaaGfs =>
+ 'National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)';
+
+ @override
+ String get dataSourceGovernmentOpenData => '政府資料開放平臺';
+
+ @override
+ String get dataSourceOpenStreetMap => '© OpenStreetMap contributors';
+
+ @override
+ String get dataSourceNasaMoon =>
+ 'National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)';
+
+ @override
+ String mapOsmDetailsHint(int enabled, int total) {
+ return 'เปิดใช้งาน $enabled จากทั้งหมด $total เลเยอร์';
+ }
+
+ @override
+ String get mapOsmSurface => 'พื้นผิว';
+
+ @override
+ String get mapOsmParks => 'สวนสาธารณะ';
+
+ @override
+ String get mapOsmLandUse => 'การใช้ที่ดิน';
+
+ @override
+ String get mapOsmAirportAreas => 'พื้นที่สนามบิน';
+
+ @override
+ String get mapOsmWater => 'พื้นที่น้ำ';
+
+ @override
+ String get mapOsmRivers => 'แม่น้ำ';
+
+ @override
+ String get mapOsmBoundaries => 'ขอบเขต';
+
+ @override
+ String get mapOsmBuildings => 'อาคาร';
+
+ @override
+ String get mapOsmRoads => 'ถนน';
+
+ @override
+ String get mapOsmRoadNames => 'ชื่อถนน';
+
+ @override
+ String get mapOsmWaterNames => 'ชื่อพื้นที่น้ำ';
+
+ @override
+ String get mapOsmPeaks => 'ยอดเขา';
+
+ @override
+ String get mapOsmAirportNames => 'ชื่อสนามบิน';
+
+ @override
+ String get mapOsmPlaceNames => 'ชื่อสถานที่';
+
+ @override
+ String get mapOsmPoi => 'จุดน่าสนใจ';
+
+ @override
+ String get mapOsmHouseNumbers => 'เลขที่บ้าน';
+
+ @override
+ String get mapOsmRestoreAll => 'คืนค่าทั้งหมด';
+
+ @override
+ String get mapOsmSectionNatural => 'ลักษณะธรรมชาติ';
+
+ @override
+ String get mapOsmSectionRoadsAndBuildings => 'ถนนและอาคาร';
+
+ @override
+ String get mapOsmSectionLabelsAndPlaces => 'ป้ายชื่อและสถานที่';
+
@override
String get mapTownLabels => 'ชื่อตำบล';
@@ -2316,10 +2427,10 @@ class AppLocalizationsTh extends AppLocalizations {
String get notifySetFailed => 'ไม่สามารถบันทึกการตั้งค่าได้ โปรดลองอีกครั้ง';
@override
- String get meshtasticDisconnect => 'Disconnect';
+ String get meshtasticDisconnect => 'ตัดการเชื่อมต่อ';
@override
- String get meshtasticUndecoded => 'Not decrypted';
+ String get meshtasticUndecoded => 'ไม่ได้ถอดรหัส';
@override
String get notifyAnnouncement => 'ประกาศ';
@@ -2856,6 +2967,55 @@ class AppLocalizationsTh extends AppLocalizations {
return '“$what” ถูกปฏิเสธไว้ และระบบจะไม่ถามอีก โปรดเปิดในการตั้งค่า';
}
+ @override
+ String get permissionGuideNotification =>
+ 'เปิดการตั้งค่าระบบเพื่ออนุญาตการแจ้งเตือน';
+
+ @override
+ String get permissionGuideForegroundLocation =>
+ 'เปิดการตั้งค่าระบบเพื่ออนุญาตตำแหน่งที่แม่นยำ';
+
+ @override
+ String permissionGuideBackgroundLocation(Object option) {
+ return 'ใน “$option” ให้เลือก “อนุญาตตลอดเวลา”';
+ }
+
+ @override
+ String get permissionGuideBackgroundExecution =>
+ 'อนุญาตการทำงานเบื้องหลังในการตั้งค่าระบบเพื่อไม่ให้หยุดการแจ้งเตือน';
+
+ @override
+ String get permissionGuideUnusedPause =>
+ 'หากแอปถูกทำเครื่องหมายเป็น “ไม่ได้ใช้” ให้เลือก “อนุญาต” ในการตั้งค่าระบบ';
+
+ @override
+ String get permissionGuideUnusedFreeSpace =>
+ 'หากแอปถูกหยุดชั่วคราวเพราะพื้นที่จัดเก็บ ให้ล้างแคชแล้วเปิดใหม่';
+
+ @override
+ String get permissionGuideUnusedRevoke =>
+ 'หากสิทธิ์ของแอปถูกเพิกถอน ให้อนุญาตอีกครั้งในการตั้งค่าระบบ';
+
+ @override
+ String get permissionGuideUnusedPlayProtect =>
+ 'หาก Play Protect หยุดแอปชั่วคราว ให้ตรวจสอบสถานะใน Google Play';
+
+ @override
+ String permissionGuideVendorPower(Object vendor) {
+ return 'ในการตั้งค่าประหยัดพลังงานของ “$vendor” ให้ตั้งค่าแอปนี้เป็น “ไม่จำกัด”';
+ }
+
+ @override
+ String get permissionStillRequired =>
+ 'ยังจำเป็น — เปิดการตั้งค่าเพื่อเปิดใช้งาน';
+
+ @override
+ String get permissionVerifyManually =>
+ 'โปรดตรวจสอบด้วยตนเองว่าสิทธิ์นี้เปิดใช้งานในการตั้งค่าระบบ';
+
+ @override
+ String get permissionBackgroundLocationOption => '“อนุญาตตลอดเวลา”';
+
@override
String get displayTextSize => 'ขนาดตัวอักษร';
@@ -3002,6 +3162,16 @@ class AppLocalizationsTh extends AppLocalizations {
String get moreDumpDiagnosticsHint =>
'อัปโหลดแล้วคัดลอกลิงก์เพื่อแนบในรายงาน';
+ @override
+ String get dumpIncludeSensitive => 'รวมตำแหน่งที่แม่นยำ';
+
+ @override
+ String get dumpIncludeSensitiveHint =>
+ 'รวมพิกัดจากบันทึกและตำแหน่งเบื้องหลัง หากไม่เลือกจะแทนค่าด้วย null';
+
+ @override
+ String get dumpUpload => 'อัปโหลด';
+
@override
String get dumpUploaded => 'อัปโหลดแล้ว';
diff --git a/lib/l10n/gen/app_localizations_vi.dart b/lib/l10n/gen/app_localizations_vi.dart
index 2ea1a21fd..5ee378d05 100644
--- a/lib/l10n/gen/app_localizations_vi.dart
+++ b/lib/l10n/gen/app_localizations_vi.dart
@@ -56,7 +56,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get restroomTypeMale => 'Nhà vệ sinh nam';
@override
- String get meshtasticLastReceived => 'Last received';
+ String get meshtasticLastReceived => 'Nhận lần cuối';
@override
String get reportDetailSortByCounty => 'Sắp xếp theo khu vực';
@@ -87,7 +87,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get homeRainTrendScattered => 'Có thể có mưa rào nhẹ';
@override
- String get meshtasticUptime => 'Uptime';
+ String get meshtasticUptime => 'Thời gian hoạt động';
@override
String get weatherRankingTempExtremes => 'Cực trị nhiệt độ';
@@ -99,7 +99,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get mapTerrainReliefHint => 'Hiển thị địa hình nổi trên bản đồ nền';
@override
- String get meshtasticEmptyMessage => '(empty message)';
+ String get meshtasticEmptyMessage => '(tin nhắn trống)';
@override
String get moreSectionRegion => 'Khu vực';
@@ -111,7 +111,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get aedHoursSaturday => 'Giờ thứ Bảy';
@override
- String get moonPhaseNew => 'New moon';
+ String get moonPhaseNew => 'Trăng mới';
@override
String get notifySectionEew => 'Cảnh báo sớm động đất';
@@ -126,7 +126,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get mapTownLabelsHint => 'Hiển thị tên hương trấn khi phóng to';
@override
- String get commonCancel => 'Cancel';
+ String get commonCancel => 'Hủy';
@override
String get notifyOptTsunamiWarning => 'Chỉ cảnh báo sóng thần';
@@ -166,7 +166,7 @@ class AppLocalizationsVi extends AppLocalizations {
@override
String get mapLayerStyleJmaTooltip =>
- 'Grayscale base, tinted below −40 °C to highlight cloud-top height';
+ 'Nền grayscale, tô màu dưới −40 °C để làm nổi bật độ cao đỉnh mây';
@override
String get mapLayerRain => 'Lượng mưa';
@@ -220,7 +220,7 @@ class AppLocalizationsVi extends AppLocalizations {
@override
String get meshtasticExcludeMqttSubtitle =>
- 'Nodes bridged over the internet, not heard by radio';
+ 'Các nút kết nối qua Internet, không nghe qua sóng radio';
@override
String get reportFilterIntensityInfoTitle => 'Thang cường độ mới và cũ';
@@ -232,14 +232,14 @@ class AppLocalizationsVi extends AppLocalizations {
String get radarOverlayMenuTooltip => 'Tùy chọn lớp radar';
@override
- String get meshtasticNodes => 'Nodes';
+ String get meshtasticNodes => 'Nút';
@override
- String get meshtasticSend => 'Send';
+ String get meshtasticSend => 'Gửi';
@override
String get typhoonOverlayStormL7Tooltip =>
- 'Level-7 wind field + average circle (purple)';
+ 'Trường gió cấp 7 + bán kính trung bình (tím)';
@override
String get aedType => 'Loại';
@@ -291,7 +291,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get skyTimeDusk => 'Chạng vạng';
@override
- String get meshtasticFirmware => 'Firmware';
+ String get meshtasticFirmware => 'Phần mềm cơ sở';
@override
String get reportFilterDateEndNote => 'Ngày kết thúc: đến 24:00(Đài Bắc)';
@@ -300,7 +300,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get reportFilterSortMagnitude => 'Độ lớn';
@override
- String get meshtasticSilent => 'Silent';
+ String get meshtasticSilent => 'Im lặng';
@override
String get mapLayerCategoryEarthquake => 'Động đất';
@@ -334,7 +334,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get notifyOptTsunamiAll => 'Tin và cảnh báo sóng thần';
@override
- String get meshtasticLayerOptions => 'Node options';
+ String get meshtasticLayerOptions => 'Tùy chọn nút';
@override
String get onboardingAgreeContinue => 'Đồng ý và tiếp tục';
@@ -343,7 +343,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get commonRetry => 'Thử lại';
@override
- String get meshtasticNodeId => 'Node ID';
+ String get meshtasticNodeId => 'ID nút';
@override
String reportDetailNumbered(String number) {
@@ -351,7 +351,7 @@ class AppLocalizationsVi extends AppLocalizations {
}
@override
- String get typhoonOverlayStormBandSubtitle => 'With average circle';
+ String get typhoonOverlayStormBandSubtitle => 'Kèm bán kính trung bình';
@override
String get disasterMapOverlayRestroomTooltip =>
@@ -379,13 +379,13 @@ class AppLocalizationsVi extends AppLocalizations {
String get sponsorRestore => 'Khôi phục giao dịch';
@override
- String get meshtasticChannelWorking => 'Setting up the DPIP channel…';
+ String get meshtasticChannelWorking => 'Đang thiết lập kênh DPIP…';
@override
- String get meshtasticRegionSwitch => 'Switch to TW';
+ String get meshtasticRegionSwitch => 'Chuyển sang vùng TW';
@override
- String get meshtasticTraffic => 'Traffic';
+ String get meshtasticTraffic => 'Lưu lượng';
@override
String get mapLayerStyleBdTooltip =>
@@ -399,10 +399,10 @@ class AppLocalizationsVi extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentNight =>
- 'Night = transparent, the basemap shows';
+ 'Ban đêm = trong suốt, thấy bản đồ nền';
@override
- String get meshtasticScanning => 'Scanning…';
+ String get meshtasticScanning => 'Đang quét…';
@override
String regionSelectFull(int max) {
@@ -474,7 +474,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get navMore => 'Thêm';
@override
- String get meshtasticDpipChannel => 'DPIP channel';
+ String get meshtasticDpipChannel => 'Kênh DPIP';
@override
String get disasterMapOverlaySectionLayers => 'Lớp';
@@ -486,7 +486,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get typhoonLabelNe => 'NE';
@override
- String get meshtasticCopied => 'Message copied';
+ String get meshtasticCopied => 'Đã sao chép tin nhắn';
@override
String get reportListEmpty => 'Không có báo cáo động đất';
@@ -498,19 +498,19 @@ class AppLocalizationsVi extends AppLocalizations {
String get mapLayerSatelliteTruecolor => 'Himawari True Color';
@override
- String get typhoonOverlaySectionExtra => 'Overlays';
+ String get typhoonOverlaySectionExtra => 'Lớp phủ';
@override
String get eewSWave => 'Sóng S';
@override
- String get meshtasticBusyTitle => 'Another app is using this radio';
+ String get meshtasticBusyTitle => 'Ứng dụng khác đang dùng radio này';
@override
String get restroomCategoryCultural => 'Địa điểm văn hóa giải trí';
@override
- String get typhoonLabelWind => 'Max. sustained wind near centre';
+ String get typhoonLabelWind => 'Gió duy trì tối đa gần tâm';
@override
String get radarGlobalOutlineHint => 'Khung ngoài của mỗi quốc gia';
@@ -522,7 +522,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get typhoonLegendCircle15 => 'Vòng gió mạnh';
@override
- String get dataSectionAstronomy => 'Astronomy';
+ String get dataSectionAstronomy => 'Thiên văn';
@override
String get homeRainTrendLightSustained => 'Mưa nhỏ tiếp diễn trong 1 giờ tới';
@@ -531,10 +531,10 @@ class AppLocalizationsVi extends AppLocalizations {
String get commonError => 'Đã xảy ra lỗi';
@override
- String get moonPhaseWaningCrescent => 'Waning crescent';
+ String get moonPhaseWaningCrescent => 'Trăng lưỡi liềm khuyết';
@override
- String get meshtasticPower => 'Power';
+ String get meshtasticPower => 'Nguồn';
@override
String get mapTimelineNow => 'Bây giờ';
@@ -562,7 +562,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get notifyTitle => 'Thông báo';
@override
- String get meshtasticTxPower => 'TX power';
+ String get meshtasticTxPower => 'Công suất TX';
@override
String get restroomCategoryLabel => 'Hạng mục';
@@ -575,7 +575,7 @@ class AppLocalizationsVi extends AppLocalizations {
'DPIP cam kết cung cấp thông tin phòng chống thiên tai theo thời gian thực, không có quảng cáo hay mô hình lợi nhuận nào khác. Sự ủng hộ của bạn giúp chúng tôi duy trì máy chủ và tiếp tục phát triển.';
@override
- String get typhoonLabelStormAvg => 'Avg. radius of Beaufort 10 winds';
+ String get typhoonLabelStormAvg => 'Bán kính trung bình gió Beaufort 10';
@override
String get restroomCategoryCommercial => 'Cơ sở thương mại';
@@ -609,10 +609,10 @@ class AppLocalizationsVi extends AppLocalizations {
String get restroomTypeUnspecified => 'Không xác định';
@override
- String get typhoonOverlayProbabilityHint => 'Hides the forecast cone';
+ String get typhoonOverlayProbabilityHint => 'Ẩn vùng dự kiến';
@override
- String get mapLayerSatelliteGlobalOutline => 'Country border';
+ String get mapLayerSatelliteGlobalOutline => 'Đường biên giới';
@override
String get mapNavTemperature => 'Nhiệt độ';
@@ -647,7 +647,7 @@ class AppLocalizationsVi extends AppLocalizations {
@override
String get typhoonOverlayWeatherRadarTooltip =>
- 'Radar echo closest to the typhoon bulletin time';
+ 'Ảnh radar gần thời điểm bản tin bão nhất';
@override
String get onboardingPermLocationDesc =>
@@ -660,13 +660,13 @@ class AppLocalizationsVi extends AppLocalizations {
String get homeActiveEventsEmpty => 'Không có sự kiện đang hiệu lực';
@override
- String get typhoonLabelPosition => 'Centre location';
+ String get typhoonLabelPosition => 'Vị trí tâm';
@override
String get weatherRankingBy => 'Theo';
@override
- String get typhoonIntensityMild => 'Mild typhoon';
+ String get typhoonIntensityMild => 'Bão yếu';
@override
String get windForecastGlobalOutlineHint => 'Khung ngoài của mỗi quốc gia';
@@ -684,10 +684,10 @@ class AppLocalizationsVi extends AppLocalizations {
String get restroomCategoryReligious => 'Nơi tôn giáo';
@override
- String get meshtasticRole => 'Role';
+ String get meshtasticRole => 'Vai trò';
@override
- String get mapLayerSatelliteCloudCloudy => 'Cloudy';
+ String get mapLayerSatelliteCloudCloudy => 'Nhiều mây';
@override
String get skyTimeSunrise => 'Bình minh';
@@ -696,7 +696,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get meshtasticJumpToLatest => 'Tới mới nhất';
@override
- String get meshtasticNoMessages => 'No messages yet';
+ String get meshtasticNoMessages => 'Chưa có tin nhắn';
@override
String get onboardingPermNotifyDesc =>
@@ -706,7 +706,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get radarTownOutline => 'Ranh giới xã phường';
@override
- String get mapLayerStyleSection => 'Colour style';
+ String get mapLayerStyleSection => 'Kiểu màu';
@override
String get disasterMapOverlayMenuTooltip => 'Lớp bản đồ phòng chống';
@@ -715,7 +715,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get moreGooglePlay => 'Google Play';
@override
- String get meshtasticOnline => 'Heard recently';
+ String get meshtasticOnline => 'Nghe thấy gần đây';
@override
String get typhoonLabelSw => 'SW';
@@ -730,7 +730,7 @@ class AppLocalizationsVi extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentClear =>
- 'Clear sky = transparent, the basemap shows';
+ 'Trời quang = trong suốt, thấy bản đồ nền';
@override
String get mapOverlaySectionReference => 'Lớp tham chiếu';
@@ -764,7 +764,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get eewArrived => 'Đã đến';
@override
- String get meshtasticNoDevices => 'No Meshtastic devices found';
+ String get meshtasticNoDevices => 'Không tìm thấy thiết bị Meshtastic';
@override
String get mapLayerCategoryLife => 'Đời sống';
@@ -773,10 +773,10 @@ class AppLocalizationsVi extends AppLocalizations {
String get reportFilterSortIntensity => 'Cường độ';
@override
- String get meshtasticStateDisconnected => 'Disconnected';
+ String get meshtasticStateDisconnected => 'Đã ngắt kết nối';
@override
- String get typhoonIntensityIntense => 'Intense typhoon';
+ String get typhoonIntensityIntense => 'Bão mạnh';
@override
String get mapLayerOrderTitle => 'Sắp xếp thứ tự lớp';
@@ -785,7 +785,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get dpmYes => 'Có';
@override
- String get meshtasticNoHistory => 'Not enough history yet';
+ String get meshtasticNoHistory => 'Lịch sử chưa đủ';
@override
String get reportDetailLocalIntensityUnavailable =>
@@ -813,10 +813,10 @@ class AppLocalizationsVi extends AppLocalizations {
String get mapLayerSatelliteMndwi => 'Himawari MNDWI';
@override
- String get typhoonOverlaySectionStorm => 'Storm wind';
+ String get typhoonOverlaySectionStorm => 'Gió bão';
@override
- String get moonPhaseFull => 'Full moon';
+ String get moonPhaseFull => 'Trăng tròn';
@override
String meshtasticBinaryPayload(String size) {
@@ -824,14 +824,14 @@ class AppLocalizationsVi extends AppLocalizations {
}
@override
- String get moonPhaseWaningGibbous => 'Waning gibbous';
+ String get moonPhaseWaningGibbous => 'Trăng khuyết lồi';
@override
String get reportFilterIntensityInfoModernTitle => 'Mới (từ 2020)';
@override
String typhoonDataTime(String time) {
- return 'Data time\n$time';
+ return 'Giờ dữ liệu\n$time';
}
@override
@@ -841,7 +841,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get moreSectionAbout => 'Giới thiệu';
@override
- String get meshtasticSelectDevice => 'Select a radio';
+ String get meshtasticSelectDevice => 'Chọn radio';
@override
String get onboardingIntroBody =>
@@ -854,19 +854,19 @@ class AppLocalizationsVi extends AppLocalizations {
String get reportDetailImage => 'Hình ảnh báo cáo';
@override
- String get meshtasticStateConfiguring => 'Configuring…';
+ String get meshtasticStateConfiguring => 'Đang cấu hình…';
@override
- String get typhoonLabelGaleAvg => 'Avg. radius of Beaufort 7 winds';
+ String get typhoonLabelGaleAvg => 'Bán kính trung bình gió Beaufort 7';
@override
String get onboardingPermNotify => 'Thông báo';
@override
- String get meshtasticClearMessages => 'Clear messages';
+ String get meshtasticClearMessages => 'Xóa tin nhắn';
@override
- String get meshtasticNotifyMessages => 'Notify on new messages';
+ String get meshtasticNotifyMessages => 'Thông báo tin nhắn mới';
@override
String get defaultMapLayerSettings => 'Lớp bản đồ mặc định';
@@ -944,7 +944,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get mapTimelineFuture => 'Tương lai';
@override
- String get typhoonLegendCircleAvg => 'Average circle';
+ String get typhoonLegendCircleAvg => 'Bán kính trung bình';
@override
String reportFilterDepthKm(String depth) {
@@ -963,7 +963,7 @@ class AppLocalizationsVi extends AppLocalizations {
}
@override
- String get typhoonLabelGust => 'Peak gust';
+ String get typhoonLabelGust => 'Gió giật đỉnh';
@override
String get mapAppGoogleMaps => 'Google Maps';
@@ -981,7 +981,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get skyTimeGolden => 'Giờ vàng';
@override
- String get moonAge => 'Age';
+ String get moonAge => 'Tuổi trăng';
@override
String get meshtasticRadioSettings => 'LoRa';
@@ -996,7 +996,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get mapLayers => 'Lớp bản đồ';
@override
- String get meshtasticHardware => 'Hardware';
+ String get meshtasticHardware => 'Phần cứng';
@override
String get languageSettings => 'Ngôn ngữ';
@@ -1010,7 +1010,7 @@ class AppLocalizationsVi extends AppLocalizations {
}
@override
- String get typhoonOverlayWeatherHint => 'Aligned to bulletin time';
+ String get typhoonOverlayWeatherHint => 'Khớp với thời điểm bản tin';
@override
String get skyTimeDawn => 'Rạng đông';
@@ -1019,7 +1019,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get skyTimeAfternoon => 'Buổi chiều';
@override
- String get meshtasticLastHeard => 'Last heard';
+ String get meshtasticLastHeard => 'Nghe thấy lần cuối';
@override
String get typhoonWarningTitle => 'Cảnh báo bão';
@@ -1070,10 +1070,10 @@ class AppLocalizationsVi extends AppLocalizations {
@override
String get typhoonOverlayStormL10Tooltip =>
- 'Level-10 wind field + average circle (yellow)';
+ 'Trường gió cấp 10 + bán kính trung bình (vàng)';
@override
- String get moonPhaseWaxingGibbous => 'Waxing gibbous';
+ String get moonPhaseWaxingGibbous => 'Trăng khuyết lồi đầu tháng';
@override
String get reportDetailTitle => 'Báo cáo động đất';
@@ -1087,10 +1087,10 @@ class AppLocalizationsVi extends AppLocalizations {
}
@override
- String get meshtasticNoNodes => 'No nodes heard yet';
+ String get meshtasticNoNodes => 'Chưa phát hiện nút nào';
@override
- String get meshtasticViaMqtt => 'Via MQTT (internet)';
+ String get meshtasticViaMqtt => 'Qua MQTT (Internet)';
@override
String get radarCountyOutline => 'Ranh giới huyện thị';
@@ -1108,11 +1108,11 @@ class AppLocalizationsVi extends AppLocalizations {
String get changelogCurrentVersion => 'Hiện tại';
@override
- String get typhoonLabelPressure => 'Central pressure';
+ String get typhoonLabelPressure => 'Áp suất trung tâm';
@override
String get typhoonOverlayForecastCalloutsTooltip =>
- 'Show forecast-point detail cards when zoomed in';
+ 'Hiển thị thẻ chi tiết điểm dự báo khi phóng to';
@override
String get aedOpenRemark => 'Ghi chú giờ mở';
@@ -1122,7 +1122,7 @@ class AppLocalizationsVi extends AppLocalizations {
'Để DPIP có thể cảnh báo bạn ngay khi thảm họa xảy ra, vui lòng cấp các quyền sau. Bạn có thể thay đổi chúng bất cứ lúc nào trong cài đặt hệ thống.';
@override
- String get typhoonOverlaySectionWeather => 'Weather underlay';
+ String get typhoonOverlaySectionWeather => 'Lớp nền thời tiết';
@override
String get notifyOptWeatherLocal => 'Chỉ vị trí hiện tại';
@@ -1131,7 +1131,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get mapNavRain => 'Mưa';
@override
- String get moonDays => 'days';
+ String get moonDays => 'ngày';
@override
String mapLegendUnit(String unit) {
@@ -1142,7 +1142,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get weatherModeClear => 'Trời quang';
@override
- String get meshtasticRadio => 'Radio';
+ String get meshtasticRadio => 'Bộ đàm';
@override
String get commonEmpty => 'Không có dữ liệu';
@@ -1151,10 +1151,10 @@ class AppLocalizationsVi extends AppLocalizations {
String get mapLayerSatelliteB01 => 'Himawari Blue (B01)';
@override
- String get meshtasticExternalPower => 'External power';
+ String get meshtasticExternalPower => 'Nguồn ngoài';
@override
- String get moonPhaseLastQuarter => 'Last quarter';
+ String get moonPhaseLastQuarter => 'Trăng bán nguyệt cuối tháng';
@override
String get reportFilterOrderAsc => 'Tăng dần';
@@ -1181,19 +1181,19 @@ class AppLocalizationsVi extends AppLocalizations {
String get restroomGradeExcellent => 'Xuất sắc';
@override
- String get meshtasticLastSent => 'Last sent';
+ String get meshtasticLastSent => 'Gửi lần cuối';
@override
- String get meshtasticName => 'Name';
+ String get meshtasticName => 'Tên';
@override
- String get meshtasticScan => 'Scan';
+ String get meshtasticScan => 'Quét';
@override
String get mapLayerCategoryForecast => 'Dự báo số';
@override
- String get meshtasticChannelFailed => 'Couldn\'t set up the DPIP channel';
+ String get meshtasticChannelFailed => 'Không thiết lập được kênh DPIP';
@override
String get themeSystem => 'Hệ thống';
@@ -1213,7 +1213,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get weatherPrecipitation => 'Lượng mưa';
@override
- String get moonNextFullMoon => 'Next full moon';
+ String get moonNextFullMoon => 'Trăng tròn kế tiếp';
@override
String get dpmSheetEmpty =>
@@ -1243,7 +1243,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get typhoonLabelNw => 'NW';
@override
- String get moonPhaseWaxingCrescent => 'Waxing crescent';
+ String get moonPhaseWaxingCrescent => 'Trăng lưỡi liềm đầu tháng';
@override
String get restroomCategoryLeisure => 'Địa điểm vui chơi giải trí';
@@ -1255,23 +1255,23 @@ class AppLocalizationsVi extends AppLocalizations {
String get aedCategory => 'Phân loại';
@override
- String get meshtasticChannels => 'Channels';
+ String get meshtasticChannels => 'Kênh';
@override
String get monitorWaiting => 'Đang chờ dữ liệu…';
@override
- String get typhoonOverlayForecastCallouts => 'Forecast tooltips';
+ String get typhoonOverlayForecastCallouts => 'Chú thích điểm dự báo';
@override
String get reportDetailEpicenter => 'Tọa độ tâm chấn';
@override
- String get meshtasticVoltage => 'Voltage';
+ String get meshtasticVoltage => 'Điện áp';
@override
String get mapLayerMeshtasticSubtitle =>
- 'LoRa mesh nodes heard by your radio';
+ 'Nút lưới LoRa radio của bạn nghe thấy';
@override
String get mapLayerWind => 'Gió';
@@ -1309,7 +1309,7 @@ class AppLocalizationsVi extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentZero =>
- 'Zero difference = transparent (no signal)';
+ 'Chênh lệch bằng 0 = trong suốt (không có tín hiệu)';
@override
String get shelterIndoorLabel => 'Trú ẩn trong nhà';
@@ -1321,7 +1321,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get reportFilterSortTime => 'Thời gian';
@override
- String get mapLayerSatelliteCloudProbablyClear => 'Probably clear';
+ String get mapLayerSatelliteCloudProbablyClear => 'Có thể quang mây';
@override
String get weatherModeThunderstorm => 'Mưa dông';
@@ -1333,7 +1333,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get reportFilterIntensityInfoLegacyTitle => 'Cũ (trước 2020)';
@override
- String get typhoonLabelSpeed => 'Past movement speed';
+ String get typhoonLabelSpeed => 'Tốc độ di chuyển';
@override
String mapAppOpenFailed(String app) {
@@ -1341,10 +1341,10 @@ class AppLocalizationsVi extends AppLocalizations {
}
@override
- String get mapLayerSatelliteRgbComposite => 'RGB composite (JMA recipe)';
+ String get mapLayerSatelliteRgbComposite => 'RGB tổng hợp (công thức JMA)';
@override
- String get meshtasticReceived => 'Received';
+ String get meshtasticReceived => 'Đã nhận';
@override
String get weatherRankingExtremeLow => 'Thấp nhất ngày';
@@ -1353,7 +1353,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get mapLayerSatelliteB10 => 'Himawari Lower Water Vapour (B10)';
@override
- String get mapLayerSatelliteCloudProbablyCloudy => 'Probably cloudy';
+ String get mapLayerSatelliteCloudProbablyCloudy => 'Có thể nhiều mây';
@override
String get mapLayerSatelliteTransparentNoWater =>
@@ -1363,10 +1363,10 @@ class AppLocalizationsVi extends AppLocalizations {
String get shelterCategoryLabel => 'Loại thảm họa';
@override
- String get meshtasticStateConnecting => 'Connecting…';
+ String get meshtasticStateConnecting => 'Đang kết nối…';
@override
- String get moonTitle => 'Moon';
+ String get moonTitle => 'Mặt Trăng';
@override
String get weatherRankingGust => 'Gió giật';
@@ -1381,7 +1381,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get notifySectionWeather => 'Thời tiết';
@override
- String get meshtasticPreset => 'Modem preset';
+ String get meshtasticPreset => 'Cấu hình modem';
@override
String get dataSectionSeismic => 'Địa chấn';
@@ -1408,13 +1408,13 @@ class AppLocalizationsVi extends AppLocalizations {
String get regionCurrent => 'Vị trí hiện tại';
@override
- String get meshtasticNotConnected => 'Not connected to a radio';
+ String get meshtasticNotConnected => 'Chưa kết nối radio';
@override
String get weatherModeSnow => 'Tuyết rơi';
@override
- String get mapLayerMeshtastic => 'Meshtastic nodes';
+ String get mapLayerMeshtastic => 'Nút Meshtastic';
@override
String get moreDeveloper => 'Thông tin gỡ lỗi';
@@ -1423,7 +1423,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get mapLayerSatelliteB14 => 'Himawari Longwave Infrared (B14)';
@override
- String get meshtasticChannelUse => 'Channel use';
+ String get meshtasticChannelUse => 'Mức dùng kênh';
@override
String get mapNavLightning => 'Sét';
@@ -1447,7 +1447,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get dpmOpenInMaps => 'Mở trong bản đồ';
@override
- String get meshtasticNotifyNodes => 'Notify on new nodes';
+ String get meshtasticNotifyNodes => 'Thông báo nút mới';
@override
String get onboardingPermCriticalDesc =>
@@ -1455,10 +1455,10 @@ class AppLocalizationsVi extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentWarm =>
- 'Clear sky (warm end) = transparent, the basemap shows';
+ 'Trời quang (đầu ấm) = trong suốt, thấy bản đồ nền';
@override
- String get meshtasticSent => 'Sent';
+ String get meshtasticSent => 'Đã gửi';
@override
String get homeForecastTitle => 'Dự báo 24 giờ';
@@ -1468,7 +1468,7 @@ class AppLocalizationsVi extends AppLocalizations {
@override
String meshtasticExcludeMqttHidden(int count) {
- return '$count hidden';
+ return 'Ẩn $count mục';
}
@override
@@ -1484,13 +1484,13 @@ class AppLocalizationsVi extends AppLocalizations {
String get reportListToday => 'Hôm nay';
@override
- String get meshtasticTapNode => 'Tap a node for details';
+ String get meshtasticTapNode => 'Chạm vào nút để xem chi tiết';
@override
String get commonLoading => 'Đang tải…';
@override
- String get typhoonIntensityModerate => 'Moderate typhoon';
+ String get typhoonIntensityModerate => 'Bão trung bình';
@override
String get mapLayerSatelliteAsh => 'Himawari Ash';
@@ -1502,14 +1502,14 @@ class AppLocalizationsVi extends AppLocalizations {
String get mapLayerCategorySatellite => 'Vệ tinh';
@override
- String get meshtasticChannelReady => 'DPIP channel ready';
+ String get meshtasticChannelReady => 'Kênh DPIP đã sẵn sàng';
@override
String get mapLayerSatelliteNightmicrophysics =>
'Himawari Night Microphysics';
@override
- String get typhoonIntensityTd => 'Tropical depression';
+ String get typhoonIntensityTd => 'Áp thấp nhiệt đới';
@override
String get reportFilterDate => 'Ngày';
@@ -1584,7 +1584,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get mapLayerSatelliteBtdSo2 => 'Himawari SO₂ / Cloud Phase';
@override
- String get meshtasticStateError => 'Error';
+ String get meshtasticStateError => 'Lỗi';
@override
String get weatherModeOvercast => 'Trời âm u';
@@ -1594,7 +1594,7 @@ class AppLocalizationsVi extends AppLocalizations {
@override
String get typhoonOverlayWarningTooltip =>
- 'Highlight counties under a typhoon warning';
+ 'Làm nổi bật các huyện đang có cảnh báo bão';
@override
String get reportFilterDatePick => 'Chọn ngày';
@@ -1609,13 +1609,13 @@ class AppLocalizationsVi extends AppLocalizations {
String get shelterOutdoorLabel => 'Trú ẩn ngoài trời';
@override
- String get meshtasticStateConnected => 'Connected';
+ String get meshtasticStateConnected => 'Đã kết nối';
@override
- String get mapNavRadar => 'Radar';
+ String get mapNavRadar => 'Ra đa';
@override
- String get mapLayerSatelliteCloudClear => 'Clear';
+ String get mapLayerSatelliteCloudClear => 'Quang mây';
@override
String eewSummary(String magnitude, String depth) {
@@ -1628,7 +1628,7 @@ class AppLocalizationsVi extends AppLocalizations {
@override
String get typhoonOverlayWeatherNoneTooltip =>
- 'No radar or infrared underlay';
+ 'Không có lớp nền radar hoặc hồng ngoại';
@override
String get radarCountyOutlineHint => 'Vẽ đè lên tiếng vọng';
@@ -1640,13 +1640,13 @@ class AppLocalizationsVi extends AppLocalizations {
String get homeRainTrendTitle => 'Mưa 1 giờ tới';
@override
- String get moonPhaseFirstQuarter => 'First quarter';
+ String get moonPhaseFirstQuarter => 'Trăng bán nguyệt đầu tháng';
@override
String get mapLayerCategoryTyphoon => 'Bão';
@override
- String get meshtasticUtilization => 'Airtime (24h)';
+ String get meshtasticUtilization => 'Thời gian phát sóng (24 giờ)';
@override
String get restroomTypeMixed => 'Nhà vệ sinh chung';
@@ -1664,7 +1664,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get mapLayerSatelliteBtdWvirw => 'Himawari Overshooting Top';
@override
- String get meshtasticReadingAge => 'Reading taken';
+ String get meshtasticReadingAge => 'Thời điểm đo';
@override
String get mapAppCallFailed => 'Thiết bị này không thể thực hiện cuộc gọi';
@@ -1685,7 +1685,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get reportDetailLocalFelt => 'Động đất cảm nhận cục bộ';
@override
- String get meshtasticDevice => 'Device';
+ String get meshtasticDevice => 'Thiết bị';
@override
String get onboardingGrant => 'Cấp quyền';
@@ -1733,7 +1733,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get reportListEmptyFiltered => 'Không có báo cáo khớp bộ lọc';
@override
- String get meshtasticExcludeMqtt => 'Hide MQTT nodes';
+ String get meshtasticExcludeMqtt => 'Ẩn nút MQTT';
@override
String get mapNavTyphoon => 'Bão';
@@ -1771,13 +1771,13 @@ class AppLocalizationsVi extends AppLocalizations {
String get navHome => 'Trang chủ';
@override
- String get meshtasticRegionLabel => 'Region';
+ String get meshtasticRegionLabel => 'Vùng';
@override
String get mapLayerSatelliteCloudtop => 'Himawari Cloud Top Temperature';
@override
- String get moonTimelineCaption => 'Phase';
+ String get moonTimelineCaption => 'Pha';
@override
String get openSourceLicenses => 'Giấy phép mã nguồn mở';
@@ -1797,7 +1797,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get radarScanRange => 'Hiện phạm vi quét';
@override
- String get meshtasticHopLimit => 'Hop limit';
+ String get meshtasticHopLimit => 'Giới hạn hop';
@override
String get weatherRankingExtremeHigh => 'Cao nhất ngày';
@@ -1812,7 +1812,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get mapLayerSatelliteNaturalcolor => 'Himawari Natural Color';
@override
- String get meshtasticAirtime => 'Air time (TX)';
+ String get meshtasticAirtime => 'Thời gian phát sóng (TX)';
@override
String shelterCapacityValue(int n) {
@@ -1825,7 +1825,7 @@ class AppLocalizationsVi extends AppLocalizations {
}
@override
- String get meshtasticSendHint => 'Message to broadcast';
+ String get meshtasticSendHint => 'Tin nhắn để phát';
@override
String monitorDelay(String value) {
@@ -1839,7 +1839,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get mapLayerSatelliteB08 => 'Himawari Upper Water Vapour (B08)';
@override
- String get meshtasticReconnecting => 'Reconnecting…';
+ String get meshtasticReconnecting => 'Đang kết nối lại…';
@override
String get radarTownOutlineSubtitle =>
@@ -1847,14 +1847,14 @@ class AppLocalizationsVi extends AppLocalizations {
@override
String get typhoonOverlayWeatherSatelliteTooltip =>
- 'Infrared closest to the typhoon bulletin time';
+ 'Ảnh hồng ngoại gần thời điểm bản tin bão nhất';
@override
String get radarScanRangeHint => 'Ngoài khung là chưa quan trắc';
@override
String typhoonPickerTd(String no) {
- return 'Tropical depression TD $no';
+ return 'Áp thấp nhiệt đới TD $no';
}
@override
@@ -1877,7 +1877,7 @@ class AppLocalizationsVi extends AppLocalizations {
'Dịch vụ vị trí đang tắt — cảnh báo khu vực không thể nhắm đúng vùng của bạn.';
@override
- String get mapLayerStyleTooltip => 'Colour style';
+ String get mapLayerStyleTooltip => 'Kiểu màu';
@override
String lightningLegendCg(int minutes) {
@@ -2004,49 +2004,49 @@ class AppLocalizationsVi extends AppLocalizations {
String get endpointServiceRts => 'RTS';
@override
- String get endpointServiceRadar => 'Radar';
+ String get endpointServiceRadar => 'Ra đa';
@override
- String get endpointServiceSatellite => 'Satellite';
+ String get endpointServiceSatellite => 'Vệ tinh';
@override
String get endpointServiceQpesums => 'QPE';
@override
- String get endpointServiceWind => 'Wind';
+ String get endpointServiceWind => 'Gió';
@override
- String get endpointServiceDpm => 'Disaster points';
+ String get endpointServiceDpm => 'Điểm thiên tai';
@override
- String get endpointServiceWeather => 'Weather';
+ String get endpointServiceWeather => 'Thời tiết';
@override
- String get endpointServiceRain => 'Rain';
+ String get endpointServiceRain => 'Mưa';
@override
- String get endpointServiceLightning => 'Lightning';
+ String get endpointServiceLightning => 'Sét';
@override
- String get endpointServiceTyphoon => 'Typhoon';
+ String get endpointServiceTyphoon => 'Bão';
@override
- String get endpointServiceReport => 'EQ reports';
+ String get endpointServiceReport => 'Báo cáo động đất';
@override
- String get endpointServiceTremStation => 'Tremor station';
+ String get endpointServiceTremStation => 'Trạm đo chấn động';
@override
- String get endpointServiceEvent => 'Events';
+ String get endpointServiceEvent => 'Sự kiện';
@override
- String get endpointServiceLocation => 'Location';
+ String get endpointServiceLocation => 'Vị trí';
@override
- String get endpointServiceNotify => 'Notifications';
+ String get endpointServiceNotify => 'Thông báo';
@override
- String get endpointServiceOther => 'Other';
+ String get endpointServiceOther => 'Khác';
@override
String get feedConnecting => 'Đang kết nối…';
@@ -2070,17 +2070,17 @@ class AppLocalizationsVi extends AppLocalizations {
@override
String get meshtasticBusyBody =>
- 'Disconnect it in the other Meshtastic app first. Two apps on one radio take each other\'s messages, so some will go missing.';
+ 'Hãy ngắt kết nối radio trong ứng dụng Meshtastic khác trước. Hai ứng dụng dùng chung một radio sẽ giành tin nhắn của nhau, một số tin sẽ bị mất.';
@override
String get meshtasticChannelNoSlot =>
- 'No free channel slot — free one on the radio';
+ 'Không có kênh trống — hãy giải phóng một kênh trên radio';
@override
String get restroomCategoryTransport => 'Giao thông';
@override
- String get meshtasticBattery => 'Battery';
+ String get meshtasticBattery => 'Pin';
@override
String get meshtasticDistance => 'Khoảng cách';
@@ -2092,14 +2092,14 @@ class AppLocalizationsVi extends AppLocalizations {
String get meshtasticBatteryTrend => 'Xu hướng pin';
@override
- String get typhoonOverlayMenuTooltip => 'Typhoon overlay options';
+ String get typhoonOverlayMenuTooltip => 'Tùy chọn lớp phủ bão';
@override
String get mapLayerSatelliteBtdOzone => 'Himawari Tropopause';
@override
String meshtasticRegionMismatch(String region) {
- return 'Radio region is $region — DPIP needs TW';
+ return 'Vùng radio là $region — DPIP cần TW';
}
@override
@@ -2117,7 +2117,7 @@ class AppLocalizationsVi extends AppLocalizations {
}
@override
- String get mapLayerStyleGrayTooltip => 'JMA grayscale — colder is whiter';
+ String get mapLayerStyleGrayTooltip => 'JMA grayscale — càng lạnh càng trắng';
@override
String get moreAnnouncements => 'Thông báo';
@@ -2129,10 +2129,16 @@ class AppLocalizationsVi extends AppLocalizations {
String get moreVersionStable => 'Bản chính thức';
@override
- String get moreVersionNotes => 'Phiên bản hiện tại';
+ String get moreVersionNotes => 'Bản cập nhật này';
@override
- String get releaseHighlightsTitle => 'Thay đổi trong bản này';
+ String get moreVersionNotesHighlightsSubtitle =>
+ 'Những thay đổi trong phiên bản này';
+
+ @override
+ String releaseHighlightsTitle(Object train) {
+ return '$train tóm tắt chính';
+ }
@override
String get releaseHighlightsTabNormal => 'Cho người dùng';
@@ -2177,16 +2183,16 @@ class AppLocalizationsVi extends AppLocalizations {
'Các mức 0–4, 5−, 5+, 6−, 6+, 7. Thanh lọc dùng thang mới; sự kiện cũ vẫn hiện nhãn cũ trong danh sách.';
@override
- String get typhoonOverlayWeatherNone => 'None';
+ String get typhoonOverlayWeatherNone => 'Không có';
@override
- String get mapLayerStyleGray => 'Grayscale (JMA)';
+ String get mapLayerStyleGray => 'Thang xám (JMA)';
@override
String get weatherModeAuto => 'Tự động';
@override
- String get typhoonLabelProbCircle => '70% probability circle';
+ String get typhoonLabelProbCircle => 'Vòng tròn xác suất 70%';
@override
String get notifyOptAll => 'Nhận tất cả';
@@ -2198,7 +2204,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get mapLayerSatelliteB07 => 'Himawari Shortwave Infrared (B07)';
@override
- String get typhoonLabelDirection => 'Past movement direction';
+ String get typhoonLabelDirection => 'Hướng di chuyển';
@override
String get regionManageTitle => 'Khu vực đã lưu';
@@ -2217,13 +2223,13 @@ class AppLocalizationsVi extends AppLocalizations {
String get onboardingPermsTitle => 'Quyền truy cập';
@override
- String get mapLayerStyleJma => 'Cloud-top enhancement (JMA)';
+ String get mapLayerStyleJma => 'Tăng tương phản mây (JMA)';
@override
String get rainInterval10m => '10 phút';
@override
- String get meshtasticConnectAnyway => 'Connect anyway';
+ String get meshtasticConnectAnyway => 'Vẫn kết nối';
@override
String reportListDayCount(int count) {
@@ -2235,7 +2241,7 @@ class AppLocalizationsVi extends AppLocalizations {
@override
String get mapLayerSatelliteTransparentReflectance =>
- 'Low reflectance / night = transparent, the basemap shows';
+ 'Phản xạ thấp / ban đêm = trong suốt, thấy bản đồ nền';
@override
String chartHourLabel(int hour) {
@@ -2247,7 +2253,7 @@ class AppLocalizationsVi extends AppLocalizations {
@override
String get typhoonOverlayProbabilityTooltip =>
- 'Show strike probability (hides the forecast cone)';
+ 'Hiển thị xác suất trúng bão (ẩn vùng dự kiến)';
@override
String get mapLayerSatelliteNdwi => 'Himawari NDWI';
@@ -2268,7 +2274,7 @@ class AppLocalizationsVi extends AppLocalizations {
String get mapLayerCategoryRadar => 'Ra đa';
@override
- String get meshtasticShortName => 'Short name';
+ String get meshtasticShortName => 'Tên ngắn';
@override
String get mapLayerSatelliteAirmass => 'Himawari Airmass';
@@ -2295,7 +2301,7 @@ class AppLocalizationsVi extends AppLocalizations {
@override
String get meshtasticRegionConfirm =>
- 'Switch this radio to the TW region? It restarts and disconnects for a moment, and every other channel on it moves too.';
+ 'Chuyển radio này sang vùng TW? Nó sẽ khởi động lại và ngắt kết nối một lúc, mọi kênh khác cũng được chuyển theo.';
@override
String get dataEarthquakeSubtitle => 'Báo cáo động đất';
@@ -2312,6 +2318,114 @@ class AppLocalizationsVi extends AppLocalizations {
@override
String get onboardingTermsTitle => 'Điều khoản Dịch vụ';
+ @override
+ String get mapOsmOverlay => 'Bản đồ chi tiết';
+
+ @override
+ String get mapOsmOverlayHint =>
+ 'Hiện đường, tòa nhà và địa danh chi tiết hơn';
+
+ @override
+ String get mapOsmDetails => 'Chi tiết lớp';
+
+ @override
+ String get moreDataSources => 'Nguồn dữ liệu';
+
+ @override
+ String get dataSourceTremNet => '探索智慧科技有限公司 — TREM-Net';
+
+ @override
+ String get dataSourceCwa => '交通部中央氣象署 (CWA)';
+
+ @override
+ String get dataSourceJma => '気象庁 (JMA)';
+
+ @override
+ String get dataSourceNcdr => '國家災害防救科技中心 (NCDR)';
+
+ @override
+ String get dataSourceEcmwf =>
+ 'European Centre for Medium-Range Weather Forecasts (ECMWF)';
+
+ @override
+ String get dataSourceNoaaGfs =>
+ 'National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)';
+
+ @override
+ String get dataSourceGovernmentOpenData => '政府資料開放平臺';
+
+ @override
+ String get dataSourceOpenStreetMap => '© OpenStreetMap contributors';
+
+ @override
+ String get dataSourceNasaMoon =>
+ 'National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)';
+
+ @override
+ String mapOsmDetailsHint(int enabled, int total) {
+ return 'Đã bật $enabled / $total lớp';
+ }
+
+ @override
+ String get mapOsmSurface => 'Bề mặt';
+
+ @override
+ String get mapOsmParks => 'Công viên';
+
+ @override
+ String get mapOsmLandUse => 'Sử dụng đất';
+
+ @override
+ String get mapOsmAirportAreas => 'Khu vực sân bay';
+
+ @override
+ String get mapOsmWater => 'Vùng nước';
+
+ @override
+ String get mapOsmRivers => 'Sông ngòi';
+
+ @override
+ String get mapOsmBoundaries => 'Ranh giới';
+
+ @override
+ String get mapOsmBuildings => 'Tòa nhà';
+
+ @override
+ String get mapOsmRoads => 'Đường bộ';
+
+ @override
+ String get mapOsmRoadNames => 'Tên đường';
+
+ @override
+ String get mapOsmWaterNames => 'Tên vùng nước';
+
+ @override
+ String get mapOsmPeaks => 'Đỉnh núi';
+
+ @override
+ String get mapOsmAirportNames => 'Tên sân bay';
+
+ @override
+ String get mapOsmPlaceNames => 'Tên địa danh';
+
+ @override
+ String get mapOsmPoi => 'Địa điểm quan tâm';
+
+ @override
+ String get mapOsmHouseNumbers => 'Số nhà';
+
+ @override
+ String get mapOsmRestoreAll => 'Khôi phục tất cả';
+
+ @override
+ String get mapOsmSectionNatural => 'Đặc điểm tự nhiên';
+
+ @override
+ String get mapOsmSectionRoadsAndBuildings => 'Đường & tòa nhà';
+
+ @override
+ String get mapOsmSectionLabelsAndPlaces => 'Nhãn & địa điểm';
+
@override
String get mapTownLabels => 'Tên hương trấn';
@@ -2319,10 +2433,10 @@ class AppLocalizationsVi extends AppLocalizations {
String get notifySetFailed => 'Không thể lưu cài đặt. Vui lòng thử lại.';
@override
- String get meshtasticDisconnect => 'Disconnect';
+ String get meshtasticDisconnect => 'Ngắt kết nối';
@override
- String get meshtasticUndecoded => 'Not decrypted';
+ String get meshtasticUndecoded => 'Chưa giải mã';
@override
String get notifyAnnouncement => 'Thông báo';
@@ -2860,6 +2974,54 @@ class AppLocalizationsVi extends AppLocalizations {
return '“$what” đã bị từ chối và hệ thống sẽ không hỏi lại. Hãy bật trong Cài đặt.';
}
+ @override
+ String get permissionGuideNotification =>
+ 'Mở Cài đặt Hệ thống để cho phép thông báo.';
+
+ @override
+ String get permissionGuideForegroundLocation =>
+ 'Mở Cài đặt Hệ thống để cho phép vị trí chính xác.';
+
+ @override
+ String permissionGuideBackgroundLocation(Object option) {
+ return 'Trong “$option”, chọn “Cho phép mọi lúc”.';
+ }
+
+ @override
+ String get permissionGuideBackgroundExecution =>
+ 'Cho phép chạy nền trong Cài đặt Hệ thống để thông báo không bị tạm dừng.';
+
+ @override
+ String get permissionGuideUnusedPause =>
+ 'Nếu ứng dụng bị đánh dấu “không sử dụng”, hãy chọn “Cho phép” trong Cài đặt Hệ thống.';
+
+ @override
+ String get permissionGuideUnusedFreeSpace =>
+ 'Nếu ứng dụng bị tạm dừng vì bộ nhớ, hãy xóa bộ nhớ đệm và mở lại.';
+
+ @override
+ String get permissionGuideUnusedRevoke =>
+ 'Nếu quyền của ứng dụng bị thu hồi, hãy cấp lại trong Cài đặt Hệ thống.';
+
+ @override
+ String get permissionGuideUnusedPlayProtect =>
+ 'Nếu Play Protect tạm dừng ứng dụng, hãy kiểm tra trạng thái trong Google Play.';
+
+ @override
+ String permissionGuideVendorPower(Object vendor) {
+ return 'Trong cài đặt tiết kiệm pin của “$vendor”, đặt ứng dụng này thành “Không giới hạn”.';
+ }
+
+ @override
+ String get permissionStillRequired => 'Vẫn cần thiết — mở Cài đặt để bật.';
+
+ @override
+ String get permissionVerifyManually =>
+ 'Vui lòng xác minh thủ công rằng quyền này đã được bật trong Cài đặt Hệ thống.';
+
+ @override
+ String get permissionBackgroundLocationOption => '“Cho phép mọi lúc”';
+
@override
String get displayTextSize => 'Cỡ chữ';
@@ -3007,6 +3169,16 @@ class AppLocalizationsVi extends AppLocalizations {
String get moreDumpDiagnosticsHint =>
'Tải lên rồi sao chép liên kết để đính kèm vào báo cáo';
+ @override
+ String get dumpIncludeSensitive => 'Bao gồm vị trí chính xác';
+
+ @override
+ String get dumpIncludeSensitiveHint =>
+ 'Bao gồm tọa độ trong nhật ký và vị trí nền; nếu không chọn, chúng được thay bằng null';
+
+ @override
+ String get dumpUpload => 'Tải lên';
+
@override
String get dumpUploaded => 'Đã tải lên';
diff --git a/lib/l10n/gen/app_localizations_yue.dart b/lib/l10n/gen/app_localizations_yue.dart
new file mode 100644
index 000000000..acc8230e8
--- /dev/null
+++ b/lib/l10n/gen/app_localizations_yue.dart
@@ -0,0 +1,3129 @@
+// ignore: unused_import
+import 'package:intl/intl.dart' as intl;
+
+import 'app_localizations.dart';
+
+// ignore_for_file: type=lint
+
+/// The translations for Yue Chinese Cantonese (`yue`).
+class AppLocalizationsYue extends AppLocalizations {
+ AppLocalizationsYue([String locale = 'yue']) : super(locale);
+
+ @override
+ String typhoonValueLat(String lat) {
+ return '北緯 $lat 度';
+ }
+
+ @override
+ String get onboardingSkipBody =>
+ '未授權定位同通知,DPIP 將冇辦法即時通知你所在地嘅地震同災害。你仍可稍後喺設定中開啟。';
+
+ @override
+ String get rainInterval24h => '24 時';
+
+ @override
+ String homeRainTrendHeavyStopping(int minutes) {
+ return '預計 $minutes 分鐘後停止下大雨';
+ }
+
+ @override
+ String get mapTimelineObserved => '觀測';
+
+ @override
+ String get mapTimelineScrubPaused => '拖動過快,影格更新已暫停;放慢速度即可恢復。';
+
+ @override
+ String get regionSelectTitle => '選擇地區';
+
+ @override
+ String get skyTimeNoon => '正午';
+
+ @override
+ String get radarCountyOutlineSubtitle => '讓縣市界線在雷達回波下仍然清楚。';
+
+ @override
+ String get mapLayerSatelliteB03 => 'ひまわり 可見光-紅(B03)';
+
+ @override
+ String get reportFilterIntensity => '震度';
+
+ @override
+ String get mapLayerLightning => '閃電';
+
+ @override
+ String get restroomTypeMale => '男廁所';
+
+ @override
+ String get meshtasticLastReceived => '最近接收';
+
+ @override
+ String get reportDetailSortByCounty => '依縣市排序';
+
+ @override
+ String get onboardingPermUnusedApp => '保持 App 啟用';
+
+ @override
+ String get onboardingPermUnusedAppDesc =>
+ 'Android 會暫停你長期未開啟嘅 App 並撤銷佢哋嘅權限,噉會令災害警報冇辦法送到你所在地。';
+
+ @override
+ String get onboardingPermBackgroundExec => '背景執行';
+
+ @override
+ String get onboardingPermBackgroundExecDesc => '關閉時,App 唔會被喚醒回報你嘅位置。';
+
+ @override
+ String get onboardingPermVendorPower => '手機廠商省電設定';
+
+ @override
+ String onboardingPermVendorPowerDesc(String brand) {
+ return '$brand 會停止你最近冇開過嘅 App 嘅背景作業。App 冇辦法偵測或變更,請手動允許。';
+ }
+
+ @override
+ String get homeRainTrendScattered => '可能會有零星降雨';
+
+ @override
+ String get meshtasticUptime => '運行時間';
+
+ @override
+ String get weatherRankingTempExtremes => '溫度極值';
+
+ @override
+ String get themeLight => '淺色';
+
+ @override
+ String get mapTerrainReliefHint => '喺底圖上顯示立體地形陰影';
+
+ @override
+ String get meshtasticEmptyMessage => '(空白訊息)';
+
+ @override
+ String get moreSectionRegion => '地區';
+
+ @override
+ String get mapLayerSatellite => 'ひまわり 紅外線(B13)';
+
+ @override
+ String get aedHoursSaturday => '週六開放時間';
+
+ @override
+ String get moonPhaseNew => '新月';
+
+ @override
+ String get notifySectionEew => '地震速報';
+
+ @override
+ String get mapResetNorth => '回到北方';
+
+ @override
+ String get rainInterval2d => '2 日';
+
+ @override
+ String get mapTownLabelsHint => '放大時顯示鄉鎮名稱';
+
+ @override
+ String get commonCancel => '取消';
+
+ @override
+ String get notifyOptTsunamiWarning => '只接收海嘯警報';
+
+ @override
+ String get mapLayerSatelliteBtdFog => 'ひまわり 夜間霧';
+
+ @override
+ String get moreSectionAdvanced => '進階';
+
+ @override
+ String get moreSectionMesh => 'Mesh 網絡';
+
+ @override
+ String get weatherRankingExtremeRange => '日溫差';
+
+ @override
+ String get permissionsTitle => '權限檢查';
+
+ @override
+ String get permissionsAttention => '權限需要處理';
+
+ @override
+ String get permissionsBody => 'DPIP 需要呢些權限才能即時通知你。收唔到警報時,通常就係其中一項尚未開啟。';
+
+ @override
+ String get notifySettingsMenu => '通知設定';
+
+ @override
+ String mapAppDefault(String app) {
+ return '$app(預設)';
+ }
+
+ @override
+ String get trendRange24h => '24 小時';
+
+ @override
+ String get mapLayerStyleJmaTooltip => '灰階為底,−40 °C 以下上色,凸顯雲頂高度';
+
+ @override
+ String get mapLayerRain => '雨量';
+
+ @override
+ String get mapLayerQpesums => '未來 1 小時降水預報';
+
+ @override
+ String get mapOverlaySectionMap => '地圖';
+
+ @override
+ String get mapTerrainRelief => '地形立體感';
+
+ @override
+ String get mapLegendCollapse => '收合圖例';
+
+ @override
+ String get updateAvailableTitle => '有新版本';
+
+ @override
+ String updateAvailableBody(String version) {
+ return '新版本 $version 已發佈。';
+ }
+
+ @override
+ String get updateSkip => '略過此次';
+
+ @override
+ String get updateViewChangelog => '前往查看';
+
+ @override
+ String get updateOpenAppStore => 'App Store';
+
+ @override
+ String get updateOpenTestFlight => 'TestFlight';
+
+ @override
+ String get updateOpenPlayStore => 'Play 商店';
+
+ @override
+ String get updateDownload => '下載更新';
+
+ @override
+ String get changelogShowSnapshots => '顯示測試版';
+
+ @override
+ String get changelogTitle => '更新日誌';
+
+ @override
+ String get reportFilterOrderDesc => '降序';
+
+ @override
+ String get meshtasticExcludeMqttSubtitle => '經網際網路橋接、並非無線電聽到嘅節點';
+
+ @override
+ String get reportFilterIntensityInfoTitle => '震度新制同舊制';
+
+ @override
+ String get mapLayerTyphoon => '颱風';
+
+ @override
+ String get radarOverlayMenuTooltip => '雷達圖層選項';
+
+ @override
+ String get meshtasticNodes => '節點';
+
+ @override
+ String get meshtasticSend => '傳送';
+
+ @override
+ String get typhoonOverlayStormL7Tooltip => '七級暴風圈+平均圓(紫色)';
+
+ @override
+ String get aedType => '場所類型';
+
+ @override
+ String get termsOfService => '服務條款';
+
+ @override
+ String get typhoonLegendCircle25 => '十級風暴風圈';
+
+ @override
+ String get sponsorTitle => '支援 DPIP';
+
+ @override
+ String get mapNavSatellite => '衛星';
+
+ @override
+ String homeRainTrendUpdated(String time) {
+ return '更新 $time';
+ }
+
+ @override
+ String get onboardingNext => '下一步';
+
+ @override
+ String get weatherRankingMergeTown => '鄉鎮';
+
+ @override
+ String get mapLayerMonitor => '強震監視器';
+
+ @override
+ String get moreYoutube => 'YouTube';
+
+ @override
+ String get sponsorSubscriptions => '訂閱制';
+
+ @override
+ String typhoonValueLon(String lon) {
+ return '東經 $lon 度';
+ }
+
+ @override
+ String get skyTime => '天空時間';
+
+ @override
+ String get weatherModeCloudy => '多雲';
+
+ @override
+ String get skyTimeDusk => '暮色';
+
+ @override
+ String get meshtasticFirmware => '韌體';
+
+ @override
+ String get reportFilterDateEndNote => '結束日:當日 24:00(台北時間)';
+
+ @override
+ String get reportFilterSortMagnitude => '規模';
+
+ @override
+ String get meshtasticSilent => '已靜默';
+
+ @override
+ String get mapLayerCategoryEarthquake => '地震';
+
+ @override
+ String get mapLayerSatelliteB12 => 'ひまわり 臭氧(B12)';
+
+ @override
+ String get restroomCategoryOther => '其他';
+
+ @override
+ String homeForecastHighLow(String high, String low) {
+ return '高 $high° · 低 $low°';
+ }
+
+ @override
+ String get locationBannerFix => '開啟設定';
+
+ @override
+ String get mapLegendExpand => '圖例';
+
+ @override
+ String get eewNone => '而家冇地震速報';
+
+ @override
+ String typhoonTyNo(String no) {
+ return 'TY $no';
+ }
+
+ @override
+ String get notifyOptTsunamiAll => '海嘯消息、海嘯警報';
+
+ @override
+ String get meshtasticLayerOptions => '節點選項';
+
+ @override
+ String get onboardingAgreeContinue => '同意並繼續';
+
+ @override
+ String get commonRetry => '重試';
+
+ @override
+ String get meshtasticNodeId => '節點 ID';
+
+ @override
+ String reportDetailNumbered(String number) {
+ return '編號 $number 顯著有感地震';
+ }
+
+ @override
+ String get typhoonOverlayStormBandSubtitle => '含平均圓';
+
+ @override
+ String get disasterMapOverlayRestroomTooltip => '顯示公廁';
+
+ @override
+ String get weatherRankingTitle => '觀測排行';
+
+ @override
+ String get homeRainTrendHeavySustained => '未來 1 小時會有持續大雨';
+
+ @override
+ String get notifySectionTsunami => '海嘯';
+
+ @override
+ String get restroomCategoryPark => '公園';
+
+ @override
+ String get moreLinkOpenFailed => '冇辦法開啟連結';
+
+ @override
+ String get themeDark => '深色';
+
+ @override
+ String get sponsorRestore => '恢復購買';
+
+ @override
+ String get meshtasticChannelWorking => '正在設定 DPIP 頻道…';
+
+ @override
+ String get meshtasticRegionSwitch => '切換為 TW';
+
+ @override
+ String get meshtasticTraffic => '流量';
+
+ @override
+ String get mapLayerStyleBdTooltip => 'Dvorak BD 曲線——熱帶氣旋強度分析嘅階梯灰階';
+
+ @override
+ String get disasterMapOverlayAedTooltip => '顯示 AED 位置';
+
+ @override
+ String get mapLayerHumidity => '濕度';
+
+ @override
+ String get mapLayerSatelliteTransparentNight => '夜間 = 透明,顯示底圖';
+
+ @override
+ String get meshtasticScanning => '掃描中…';
+
+ @override
+ String regionSelectFull(int max) {
+ return '最多只能選擇 $max 個地區';
+ }
+
+ @override
+ String get meshtasticNewMessages => '新訊息';
+
+ @override
+ String get meshtasticBatteryHistory => '電量歷史';
+
+ @override
+ String get meshtasticStatAvg => '平均';
+
+ @override
+ String get meshtasticStatPeak => '峰值';
+
+ @override
+ String get meshtasticStatDrain => '掉電';
+
+ @override
+ String get meshtasticStatEta => '預估可用';
+
+ @override
+ String get meshtasticStatFull => '充滿';
+
+ @override
+ String get meshtasticStatTrend => '趨勢';
+
+ @override
+ String get meshtasticStatCharging => '充電中';
+
+ @override
+ String get meshtasticStatStable => '穩定';
+
+ @override
+ String get meshtasticNodesTotal => '已知';
+
+ @override
+ String get meshtasticNodesOnline => '在線';
+
+ @override
+ String get meshtasticRx => '接收';
+
+ @override
+ String get meshtasticTx => '發送';
+
+ @override
+ String get meshtasticNodesHistory => '節點數歷史';
+
+ @override
+ String get meshtasticTrafficHistory => '流量歷史';
+
+ @override
+ String meshtasticEtaHours(int n) {
+ return '約 $n 小時';
+ }
+
+ @override
+ String meshtasticEtaDays(int n) {
+ return '約 $n 天';
+ }
+
+ @override
+ String get meshtasticTitle => 'Meshtastic';
+
+ @override
+ String get navMore => '更多';
+
+ @override
+ String get meshtasticDpipChannel => 'DPIP 頻道';
+
+ @override
+ String get disasterMapOverlaySectionLayers => '圖層';
+
+ @override
+ String get mapLayerSatelliteB05 => 'ひまわり 近紅外(B05)';
+
+ @override
+ String get typhoonLabelNe => '東北側';
+
+ @override
+ String get meshtasticCopied => '已複製訊息';
+
+ @override
+ String get reportListEmpty => '而家冇地震報告';
+
+ @override
+ String get reportListEnd => '已到最後一頁';
+
+ @override
+ String get mapLayerSatelliteTruecolor => 'ひまわり 真彩色';
+
+ @override
+ String get typhoonOverlaySectionExtra => '覆蓋層';
+
+ @override
+ String get eewSWave => '震波';
+
+ @override
+ String get meshtasticBusyTitle => '另一個 App 正在使用呢台裝置';
+
+ @override
+ String get restroomCategoryCultural => '文化育樂活動場所';
+
+ @override
+ String get typhoonLabelWind => '近中心最大風速';
+
+ @override
+ String get radarGlobalOutlineHint => '各國國界外框';
+
+ @override
+ String get notifyEvacuation => '防災資訊';
+
+ @override
+ String get typhoonLegendCircle15 => '七級風暴風圈';
+
+ @override
+ String get dataSectionAstronomy => '天文';
+
+ @override
+ String get homeRainTrendLightSustained => '未來 1 小時會有持續小雨';
+
+ @override
+ String get commonError => '發生錯誤';
+
+ @override
+ String get moonPhaseWaningCrescent => '殘月';
+
+ @override
+ String get meshtasticPower => '電力';
+
+ @override
+ String get mapTimelineNow => '而家';
+
+ @override
+ String reportFilterRange(String start, String end) {
+ return '$start – $end';
+ }
+
+ @override
+ String get reportDetailOpenReport => '報告頁面';
+
+ @override
+ String get trendRange7d => '7 天';
+
+ @override
+ String typhoonWarningAreas(String areas) {
+ return '警戒區域:$areas';
+ }
+
+ @override
+ String get rainIntervalSection => '統計時間';
+
+ @override
+ String get notifyTitle => '通知';
+
+ @override
+ String get meshtasticTxPower => '發射功率';
+
+ @override
+ String get restroomCategoryLabel => '類別';
+
+ @override
+ String get sponsorRestoring => '正在恢復購買…';
+
+ @override
+ String get sponsorIntro =>
+ 'DPIP 致力於提供即時防災資訊,冇廣告或其他營利模式。你嘅支援能幫助我哋維持伺服器運作並持續開發。';
+
+ @override
+ String get typhoonLabelStormAvg => '十級風平均暴風半徑';
+
+ @override
+ String get restroomCategoryCommercial => '商業營業場所';
+
+ @override
+ String get aedRegion => '縣市區域';
+
+ @override
+ String homeRainTrendLightStopping(int minutes) {
+ return '預計 $minutes 分鐘後停止下小雨';
+ }
+
+ @override
+ String get reportDetailInfo => '詳細資訊';
+
+ @override
+ String get mapNavWind => '風向';
+
+ @override
+ String get windForecastOverlayMenuTooltip => '風場預報圖層選項';
+
+ @override
+ String homeRainTrendMinute(int minute) {
+ return '$minute分';
+ }
+
+ @override
+ String get rainInterval6h => '6 時';
+
+ @override
+ String get restroomTypeUnspecified => '未設定';
+
+ @override
+ String get typhoonOverlayProbabilityHint => '會隱藏預測圓錐';
+
+ @override
+ String get mapLayerSatelliteGlobalOutline => '國界';
+
+ @override
+ String get mapNavTemperature => '溫度';
+
+ @override
+ String get typhoonLegendForecastPoint => '預測點';
+
+ @override
+ String get reportListYesterday => '昨天';
+
+ @override
+ String get moreSectionLinks => '相關連結';
+
+ @override
+ String get feedOffline => '連接中斷';
+
+ @override
+ String get mapLayerStyleBd => 'Dvorak BD';
+
+ @override
+ String get moreSectionDisplay => '顯示';
+
+ @override
+ String get rainInterval3d => '3 日';
+
+ @override
+ String get defaultMapLayerSubtitle => '開啟地圖分頁時顯示此圖層,底部導覽列圖示同文字會一併更新。';
+
+ @override
+ String get aedDescription => '備註';
+
+ @override
+ String get typhoonOverlayWeatherRadarTooltip => '雷達回波(對齊颱風報文時間)';
+
+ @override
+ String get onboardingPermLocationDesc => '依你所在位置推送本地警報。';
+
+ @override
+ String get mapLayerSatelliteB16 => 'ひまわり 二氧化碳(B16)';
+
+ @override
+ String get homeActiveEventsEmpty => '而家冇生效中嘅事件';
+
+ @override
+ String get typhoonLabelPosition => '中心位置';
+
+ @override
+ String get weatherRankingBy => '依';
+
+ @override
+ String get typhoonIntensityMild => '輕度颱風';
+
+ @override
+ String get windForecastGlobalOutlineHint => '各國國界外框';
+
+ @override
+ String get rainInterval1h => '1 時';
+
+ @override
+ String get eewLocalIntensity => '所在地預估';
+
+ @override
+ String get mapLayerRadar => '雷達合成回波圖';
+
+ @override
+ String get restroomCategoryReligious => '宗教禮儀場所';
+
+ @override
+ String get meshtasticRole => '角色';
+
+ @override
+ String get mapLayerSatelliteCloudCloudy => '有雲';
+
+ @override
+ String get skyTimeSunrise => '日出';
+
+ @override
+ String get meshtasticJumpToLatest => '跳到最新';
+
+ @override
+ String get meshtasticNoMessages => '尚無訊息';
+
+ @override
+ String get onboardingPermNotifyDesc => '在地震、天氣同災害發生時,即時傳遞警報通知。';
+
+ @override
+ String get radarTownOutline => '鄉鎮界線';
+
+ @override
+ String get mapLayerStyleSection => '顯示樣式';
+
+ @override
+ String get disasterMapOverlayMenuTooltip => '防災地圖圖層';
+
+ @override
+ String get moreGooglePlay => 'Google Play';
+
+ @override
+ String get meshtasticOnline => '近期聽到';
+
+ @override
+ String get typhoonLabelSw => '西南側';
+
+ @override
+ String typhoonForecastLead(String hours) {
+ return '預測 +$hours 小時';
+ }
+
+ @override
+ String get changelogTypeStable => '正式版';
+
+ @override
+ String get mapLayerSatelliteTransparentClear => '晴空 = 透明,顯示底圖';
+
+ @override
+ String get mapOverlaySectionReference => '參考圖層';
+
+ @override
+ String get mapLayerSatelliteB02 => 'ひまわり 可見光-綠(B02)';
+
+ @override
+ String get weatherRankingEmpty => '而家冇可排序嘅觀測';
+
+ @override
+ String get notifySectionOther => '其他';
+
+ @override
+ String weatherRankingMeta(String time, int count) {
+ return '資料時間:$time\n共 $count 觀測點';
+ }
+
+ @override
+ String get onboardingTermsAgree => '我已閱讀並同意服務條款';
+
+ @override
+ String get mapLayerSatelliteTransparentNoVegetation => '< 0.1 = 透明(無植被)';
+
+ @override
+ String get notifyOptLocalIntensity4 => '所在地震度4以上';
+
+ @override
+ String get eewArrived => '已抵達';
+
+ @override
+ String get meshtasticNoDevices => '找唔到 Meshtastic 裝置';
+
+ @override
+ String get mapLayerCategoryLife => '生活';
+
+ @override
+ String get reportFilterSortIntensity => '震度';
+
+ @override
+ String get meshtasticStateDisconnected => '未連線';
+
+ @override
+ String get typhoonIntensityIntense => '強烈颱風';
+
+ @override
+ String get mapLayerOrderTitle => '調整圖層順序';
+
+ @override
+ String get dpmYes => '係';
+
+ @override
+ String get meshtasticNoHistory => '歷史紀錄還唔夠';
+
+ @override
+ String get reportDetailLocalIntensityUnavailable => '冇震度訊息';
+
+ @override
+ String get mapLayerWindForecastGfs => 'GFS';
+
+ @override
+ String get reportFilterDepth => '深度';
+
+ @override
+ String get onboardingScrollHint => '向下捲動以繼續';
+
+ @override
+ String get mapNavQpesums => '預報';
+
+ @override
+ String get notifyAdvisory => '天氣警告及特報';
+
+ @override
+ String get reportFilterReset => '重設';
+
+ @override
+ String get mapLayerSatelliteMndwi => 'ひまわり 改良水體指數';
+
+ @override
+ String get typhoonOverlaySectionStorm => '暴風圈';
+
+ @override
+ String get moonPhaseFull => '滿月';
+
+ @override
+ String meshtasticBinaryPayload(String size) {
+ return '二進位內容 · $size';
+ }
+
+ @override
+ String get moonPhaseWaningGibbous => '虧凸月';
+
+ @override
+ String get reportFilterIntensityInfoModernTitle => '新制(2020 起)';
+
+ @override
+ String typhoonDataTime(String time) {
+ return '資料時間\n$time';
+ }
+
+ @override
+ String get restroomTypeAccessible => '無障礙廁所';
+
+ @override
+ String get moreSectionAbout => '關於';
+
+ @override
+ String get meshtasticSelectDevice => '選擇裝置';
+
+ @override
+ String get onboardingIntroBody =>
+ 'DPIP 係同你並肩嘅防災夥伴,整合強震即時警報、地震報告、天氣同各類災害資訊,喺關鍵時刻即時通知你。\n\n• 地震:強震即時警報、震度速報同地震報告\n• 天氣:雷暴即時訊息、天氣警告及特報\n• 海嘯同防災資訊\n\n接下來,我哋會請你閱讀服務條款,並授權幾項讓 DPIP 能即時守護你嘅權限。';
+
+ @override
+ String get shelterCapacityLabel => '收容人數';
+
+ @override
+ String get reportDetailImage => '地震報告圖';
+
+ @override
+ String get meshtasticStateConfiguring => '設定中…';
+
+ @override
+ String get typhoonLabelGaleAvg => '七級風平均暴風半徑';
+
+ @override
+ String get onboardingPermNotify => '通知';
+
+ @override
+ String get meshtasticClearMessages => '清除訊息';
+
+ @override
+ String get meshtasticNotifyMessages => '新訊息通知';
+
+ @override
+ String get defaultMapLayerSettings => '地圖預設圖層';
+
+ @override
+ String get eewSourceSettings => '地震速報來源';
+
+ @override
+ String get eewSourceSubtitle => '選擇要顯示哪些機構發布嘅地震速報。';
+
+ @override
+ String get eewSourceAll => '所有來源';
+
+ @override
+ String get eewSourceAllDescription => '顯示所有機構發布嘅地震速報。';
+
+ @override
+ String get eewSourceCwaOnly => '僅中央氣象署';
+
+ @override
+ String get eewSourceCwaOnlyDescription => '只顯示中央氣象署發布嘅地震速報。';
+
+ @override
+ String get moreSectionNotify => '通知';
+
+ @override
+ String get notifyUnavailable => '推送尚未就緒,請稍後再試。';
+
+ @override
+ String get mapLayerOrderReset => '回復預設順序';
+
+ @override
+ String get weatherRankingMergeCounty => '縣市';
+
+ @override
+ String get moreSectionApp => '取得 App';
+
+ @override
+ String get moreSectionBeta => '測試版';
+
+ @override
+ String get moreAndroidBeta => 'Android 測試版';
+
+ @override
+ String get moreTestFlight => 'iOS 測試版(TestFlight)';
+
+ @override
+ String get moreSectionPartners => '合作夥伴';
+
+ @override
+ String get morePartnersNote => '依合作時間先後排列。感謝呢些個人同公司對防災嘅貢獻,佢哋讓 DPIP 成為可能。';
+
+ @override
+ String get morePartnerGeoscience => '巨科資訊有限公司';
+
+ @override
+ String get morePartnerTwds => '台灣數位串流有限公司';
+
+ @override
+ String get reportFilterIntensityInfoLegacyBody => '震度僅 0–7,冇 5弱/5強/6弱/6強。';
+
+ @override
+ String get mapLayerSatelliteSst => 'ひまわり 海表溫度';
+
+ @override
+ String get qpesumsOverlayMenuTooltip => '定量降水預報圖層選項';
+
+ @override
+ String get mapTimelineFuture => '未來';
+
+ @override
+ String get typhoonLegendCircleAvg => '平均圓';
+
+ @override
+ String reportFilterDepthKm(String depth) {
+ return '$depth 公里';
+ }
+
+ @override
+ String get typhoonLabelSe => '東南側';
+
+ @override
+ String get radarTownOutlineHint => '較細嘅分區';
+
+ @override
+ String eewCountdown(int seconds) {
+ return '$seconds 秒';
+ }
+
+ @override
+ String get typhoonLabelGust => '瞬間最大陣風';
+
+ @override
+ String get mapAppGoogleMaps => 'Google Maps';
+
+ @override
+ String get sponsorTerms => '使用條款';
+
+ @override
+ String get restroomTypeGenderNeutral => '性別友善廁所';
+
+ @override
+ String get notifyThunderstorm => '雷暴即時訊息';
+
+ @override
+ String get skyTimeGolden => '黃金時刻';
+
+ @override
+ String get moonAge => '月齡';
+
+ @override
+ String get meshtasticRadioSettings => 'LoRa';
+
+ @override
+ String get moreGithub => 'ExpTech GitHub';
+
+ @override
+ String get homeForecastUnavailable => '選擇地區後可查看預報';
+
+ @override
+ String get mapLayers => '圖層';
+
+ @override
+ String get meshtasticHardware => '硬體';
+
+ @override
+ String get languageSettings => '語言設定';
+
+ @override
+ String get language => '語言';
+
+ @override
+ String homeForecastFeelsLike(String temp) {
+ return '體感 $temp°';
+ }
+
+ @override
+ String get typhoonOverlayWeatherHint => '對齊報文時間';
+
+ @override
+ String get skyTimeDawn => '黎明';
+
+ @override
+ String get skyTimeAfternoon => '下午';
+
+ @override
+ String get meshtasticLastHeard => '最後聽到';
+
+ @override
+ String get typhoonWarningTitle => '颱風警報';
+
+ @override
+ String get moreSourceCode => '原始碼';
+
+ @override
+ String get mapLayerCategoryWeather => '氣象觀測';
+
+ @override
+ String get mapLayerSatelliteB09 => 'ひまわり 中層水氣(B09)';
+
+ @override
+ String get windForecastTownOutlineHint => '更細嘅網格';
+
+ @override
+ String get mapLayerSatelliteCloudmask => 'ひまわり 雲遮罩';
+
+ @override
+ String get mapAppCopyCoordinates => '複製座標';
+
+ @override
+ String get reportFilterIntensityInfoIntro =>
+ '中央氣象署自 2020 年 1 月 1 日(臺北時間)起改用新制震度。';
+
+ @override
+ String get mapNavEarthquake => '地震';
+
+ @override
+ String get restroomGradeAverage => '普通級';
+
+ @override
+ String get mapLayerSatelliteBtdCo2 => 'ひまわり 卷雲/雲高';
+
+ @override
+ String get onboardingPermBackgroundDesc => '選擇「一律允許」,關閉 App 都能推送本地警報。';
+
+ @override
+ String get mapTimelineForecast => '預報';
+
+ @override
+ String get restroomTypeLabel => '廁所類型';
+
+ @override
+ String get navEarthquake => '地震';
+
+ @override
+ String get typhoonOverlayStormL10Tooltip => '十級暴風圈+平均圓(黃色)';
+
+ @override
+ String get moonPhaseWaxingGibbous => '盈凸月';
+
+ @override
+ String get reportDetailTitle => '地震報告';
+
+ @override
+ String get moreTremReport => 'TREM 偵測報告';
+
+ @override
+ String weatherDataTime(String station, String time) {
+ return '$station ∙ 資料時間 $time';
+ }
+
+ @override
+ String get meshtasticNoNodes => '尚未聽到任何節點';
+
+ @override
+ String get meshtasticViaMqtt => '經 MQTT(網際網路)';
+
+ @override
+ String get radarCountyOutline => '縣市界線';
+
+ @override
+ String get commonClose => '關閉';
+
+ @override
+ String get restroomGradeLabel => '等級';
+
+ @override
+ String get rainIntervalNow => '今日';
+
+ @override
+ String get changelogCurrentVersion => '而家版本';
+
+ @override
+ String get typhoonLabelPressure => '中心氣壓';
+
+ @override
+ String get typhoonOverlayForecastCalloutsTooltip => '放大時顯示預測點詳細卡片';
+
+ @override
+ String get aedOpenRemark => '開放時間備註';
+
+ @override
+ String get onboardingPermsBody => '為咗喺災害發生嘅第一時間通知你,請授權以下權限。你隨時可以喺系統設定中更改。';
+
+ @override
+ String get typhoonOverlaySectionWeather => '天氣底圖';
+
+ @override
+ String get notifyOptWeatherLocal => '接收所在地';
+
+ @override
+ String get mapNavRain => '雨量';
+
+ @override
+ String get moonDays => '天';
+
+ @override
+ String mapLegendUnit(String unit) {
+ return '單位:$unit';
+ }
+
+ @override
+ String get weatherModeClear => '晴天';
+
+ @override
+ String get meshtasticRadio => '電台';
+
+ @override
+ String get commonEmpty => '冇資料';
+
+ @override
+ String get mapLayerSatelliteB01 => 'ひまわり 可見光-藍(B01)';
+
+ @override
+ String get meshtasticExternalPower => '外部供電';
+
+ @override
+ String get moonPhaseLastQuarter => '下弦月';
+
+ @override
+ String get reportFilterOrderAsc => '升序';
+
+ @override
+ String get reportFilterApply => '套用';
+
+ @override
+ String get reportDetailImageUnavailable => '報告圖尚未提供';
+
+ @override
+ String get weatherRankingHighest => '最高';
+
+ @override
+ String get reportDetailReplay => '重播';
+
+ @override
+ String get mapLayerRestroom => '公廁';
+
+ @override
+ String get restroomCategoryWelfare => '社福機構、集會場所';
+
+ @override
+ String get restroomGradeExcellent => '特優級';
+
+ @override
+ String get meshtasticLastSent => '最近送出';
+
+ @override
+ String get meshtasticName => '名稱';
+
+ @override
+ String get meshtasticScan => '掃描';
+
+ @override
+ String get mapLayerCategoryForecast => '數值預報';
+
+ @override
+ String get meshtasticChannelFailed => '冇辦法設定 DPIP 頻道';
+
+ @override
+ String get themeSystem => '跟隨系統';
+
+ @override
+ String get mapLayerSatelliteNdvi => 'ひまわり 植生指數';
+
+ @override
+ String get typhoonLegendForecast => '預測路徑';
+
+ @override
+ String typhoonValueHpa(String n) {
+ return '$n 百帕';
+ }
+
+ @override
+ String get weatherPrecipitation => '降水量';
+
+ @override
+ String get moonNextFullMoon => '下次滿月';
+
+ @override
+ String get dpmSheetEmpty => '點選地圖上嘅標記查看詳情';
+
+ @override
+ String get onboardingSkipLeave => '仍要略過';
+
+ @override
+ String get aedPlaceDesc => '放置位置講明';
+
+ @override
+ String get onboardingSkipTitle => '尚未完成授權';
+
+ @override
+ String get restroomTypeFamily => '親子廁所';
+
+ @override
+ String typhoonValueKm(String n) {
+ return '$n 公里';
+ }
+
+ @override
+ String get onboardingPermBattery => '省電白名單';
+
+ @override
+ String get typhoonLabelNw => '西北側';
+
+ @override
+ String get moonPhaseWaxingCrescent => '眉月';
+
+ @override
+ String get restroomCategoryLeisure => '休閒娛樂場所';
+
+ @override
+ String get mapLayerTemperature => '溫度';
+
+ @override
+ String get aedCategory => '場所分類';
+
+ @override
+ String get meshtasticChannels => '頻道';
+
+ @override
+ String get monitorWaiting => '等待資料…';
+
+ @override
+ String get typhoonOverlayForecastCallouts => '預測點資訊';
+
+ @override
+ String get reportDetailEpicenter => '震央座標';
+
+ @override
+ String get meshtasticVoltage => '電壓';
+
+ @override
+ String get mapLayerMeshtasticSubtitle => '電台聽到過嘅 LoRa 網狀網路節點';
+
+ @override
+ String get mapLayerWind => '風向';
+
+ @override
+ String get reportDetailMagnitude => '地震規模';
+
+ @override
+ String get reportDetailAreaIntensity => '各地震度';
+
+ @override
+ String get rainInterval12h => '12 時';
+
+ @override
+ String reportListMagnitude(String magnitude) {
+ return 'M$magnitude';
+ }
+
+ @override
+ String get notifyMonitor => '強震監視器';
+
+ @override
+ String get onboardingStart => '開始使用';
+
+ @override
+ String sponsorPerMonth(String price) {
+ return '$price / 月';
+ }
+
+ @override
+ String get mapLayerPressure => '氣壓';
+
+ @override
+ String get mapLayerSatelliteB04 => 'ひまわり 近紅外(B04)';
+
+ @override
+ String get mapLayerSatelliteTransparentZero => '零差值 = 透明(無訊號)';
+
+ @override
+ String get shelterIndoorLabel => '室內收容';
+
+ @override
+ String get notifyOptOff => '關閉';
+
+ @override
+ String get reportFilterSortTime => '時間';
+
+ @override
+ String get mapLayerSatelliteCloudProbablyClear => '可能晴空';
+
+ @override
+ String get weatherModeThunderstorm => '雷暴';
+
+ @override
+ String get homeViewOnMap => '前往地圖查看';
+
+ @override
+ String get reportFilterIntensityInfoLegacyTitle => '舊制(2020 以前)';
+
+ @override
+ String get typhoonLabelSpeed => '過去移動時速';
+
+ @override
+ String mapAppOpenFailed(String app) {
+ return '冇辦法開啟 $app';
+ }
+
+ @override
+ String get mapLayerSatelliteRgbComposite => 'RGB 合成(JMA 配方)';
+
+ @override
+ String get meshtasticReceived => '已接收';
+
+ @override
+ String get weatherRankingExtremeLow => '今日最低';
+
+ @override
+ String get mapLayerSatelliteB10 => 'ひまわり 低層水氣(B10)';
+
+ @override
+ String get mapLayerSatelliteCloudProbablyCloudy => '可能有雲';
+
+ @override
+ String get mapLayerSatelliteTransparentNoWater => '≤ 0 = 透明(無水體)';
+
+ @override
+ String get shelterCategoryLabel => '適用災害';
+
+ @override
+ String get meshtasticStateConnecting => '連線中…';
+
+ @override
+ String get moonTitle => '月亮';
+
+ @override
+ String get weatherRankingGust => '陣風';
+
+ @override
+ String get moreAppStore => 'App Store';
+
+ @override
+ String get moreServerStatus => '伺服器狀態';
+
+ @override
+ String get notifySectionWeather => '天氣';
+
+ @override
+ String get meshtasticPreset => '調變預設';
+
+ @override
+ String get dataSectionSeismic => '地震';
+
+ @override
+ String get changelogBodyEmpty => '此版本冇講明。';
+
+ @override
+ String get changelogOpenOnGitHub => '喺 GitHub 查看';
+
+ @override
+ String get radarGlobalOutline => '國界';
+
+ @override
+ String get notifyEew => '緊急地震速報';
+
+ @override
+ String get regionNationwide => '全國';
+
+ @override
+ String get moreNotifyLog => 'DPIP 通知發送記錄';
+
+ @override
+ String get regionCurrent => '所在地';
+
+ @override
+ String get meshtasticNotConnected => '尚未連線至裝置';
+
+ @override
+ String get weatherModeSnow => '下雪';
+
+ @override
+ String get mapLayerMeshtastic => 'Meshtastic 節點';
+
+ @override
+ String get moreDeveloper => '偵錯資訊';
+
+ @override
+ String get mapLayerSatelliteB14 => 'ひまわり 長波紅外線(B14)';
+
+ @override
+ String get meshtasticChannelUse => '頻道使用率';
+
+ @override
+ String get mapNavLightning => '閃電';
+
+ @override
+ String get homeForecastEmpty => '而家冇預報資料';
+
+ @override
+ String get sponsorOneTime => '單次支援';
+
+ @override
+ String get mapLayerSatelliteBtdSplit => 'ひまわり 分割視窗';
+
+ @override
+ String get onboardingPermBackground => '背景定位';
+
+ @override
+ String get aedEmergencyPhone => '緊急聯絡電話';
+
+ @override
+ String get dpmOpenInMaps => '開啟地圖';
+
+ @override
+ String get meshtasticNotifyNodes => '新節點通知';
+
+ @override
+ String get onboardingPermCriticalDesc => '讓危及生命嘅強震即時警報,即使喺靜音或勿擾模式下都能發出聲響。';
+
+ @override
+ String get mapLayerSatelliteTransparentWarm => '晴空(暖端) = 透明,顯示底圖';
+
+ @override
+ String get meshtasticSent => '已送出';
+
+ @override
+ String get homeForecastTitle => '24小時預報';
+
+ @override
+ String get typhoonLegendWarningAreas => '警報區域';
+
+ @override
+ String meshtasticExcludeMqttHidden(int count) {
+ return '已隱藏 $count 個';
+ }
+
+ @override
+ String get notifyOptLocalIntensity1 => '所在地震度1以上';
+
+ @override
+ String get mapTimelinePast => '歷史';
+
+ @override
+ String get restroomTypeFemale => '女廁所';
+
+ @override
+ String get reportListToday => '今天';
+
+ @override
+ String get meshtasticTapNode => '點選節點查看詳細資訊';
+
+ @override
+ String get commonLoading => '載入中…';
+
+ @override
+ String get typhoonIntensityModerate => '中度颱風';
+
+ @override
+ String get mapLayerSatelliteAsh => 'ひまわり 火山灰';
+
+ @override
+ String get rainInterval3h => '3 時';
+
+ @override
+ String get mapLayerCategorySatellite => '衛星';
+
+ @override
+ String get meshtasticChannelReady => 'DPIP 頻道已就緒';
+
+ @override
+ String get mapLayerSatelliteNightmicrophysics => 'ひまわり 夜間微物理';
+
+ @override
+ String get typhoonIntensityTd => '熱帶性低氣壓';
+
+ @override
+ String get reportFilterDate => '日期';
+
+ @override
+ String get sponsorRestoreUnavailable => '冇辦法連線至商店,請稍後再試';
+
+ @override
+ String homeForecastPop(String pop) {
+ return '$pop%';
+ }
+
+ @override
+ String get regionEmpty => '尚未新增常用地區';
+
+ @override
+ String get onboardingPermBatteryDesc => '允許 DPIP 喺背景持續運作,避免警報延遲或漏收。';
+
+ @override
+ String get mapNavDisaster => '防災';
+
+ @override
+ String get radarScanRangeSubtitle => '標示四座雷達實際觀測到嘅範圍。';
+
+ @override
+ String get aedHoursSunday => '週日開放時間';
+
+ @override
+ String get reportDetailOriginTime => '發震時間';
+
+ @override
+ String get trendNoData => '冇趨勢資料';
+
+ @override
+ String get onboardingPermLocation => '定位';
+
+ @override
+ String get moreDiscord => 'Discord 社群';
+
+ @override
+ String get mapNavPressure => '氣壓';
+
+ @override
+ String get mapLayerSatelliteB13 => 'ひまわり 紅外線(B13)';
+
+ @override
+ String typhoonTdNo(String no) {
+ return 'TD $no';
+ }
+
+ @override
+ String get changelogEmpty => '而家冇更新日誌';
+
+ @override
+ String get reportFilterDateStartNote => '開始日:當日 00:00(台北時間)';
+
+ @override
+ String get eewTitle => '地震速報';
+
+ @override
+ String get mapLayerWindForecastEcmwf => 'ECMWF';
+
+ @override
+ String regionSelectCount(int count, int max) {
+ return '已選 $count/$max';
+ }
+
+ @override
+ String get mapLayerSatelliteBtdSo2 => 'ひまわり 二氧化硫/雲相';
+
+ @override
+ String get meshtasticStateError => '錯誤';
+
+ @override
+ String get weatherModeOvercast => '陰天';
+
+ @override
+ String get reportDetailDepth => '震源深度';
+
+ @override
+ String get typhoonOverlayWarningTooltip => '標示警報區域縣市';
+
+ @override
+ String get reportFilterDatePick => '選擇日期';
+
+ @override
+ String get onboardingSkipStay => '返回授權';
+
+ @override
+ String get commonFetchFailed => '冇辦法獲取資料,請稍後重試';
+
+ @override
+ String get shelterOutdoorLabel => '室外收容';
+
+ @override
+ String get meshtasticStateConnected => '已連線';
+
+ @override
+ String get mapNavRadar => '雷達';
+
+ @override
+ String get mapLayerSatelliteCloudClear => '晴空';
+
+ @override
+ String eewSummary(String magnitude, String depth) {
+ return '規模 $magnitude・深度 $depth 公里';
+ }
+
+ @override
+ String get locationBannerPermission => '尚未授權定位,冇辦法針對你嘅所在地推送警報。';
+
+ @override
+ String get typhoonOverlayWeatherNoneTooltip => '唔疊雷達或紅外線';
+
+ @override
+ String get radarCountyOutlineHint => '畫喺回波上面';
+
+ @override
+ String get windForecastCountyOutlineHint => '繪製喺風場上面';
+
+ @override
+ String get homeRainTrendTitle => '近 1 小時降水趨勢';
+
+ @override
+ String get moonPhaseFirstQuarter => '上弦月';
+
+ @override
+ String get mapLayerCategoryTyphoon => '颱風';
+
+ @override
+ String get meshtasticUtilization => '空中工時(24 小時)';
+
+ @override
+ String get restroomTypeMixed => '混合廁所';
+
+ @override
+ String get restroomGradeGood => '優等級';
+
+ @override
+ String get notifyTsunami => '海嘯資訊';
+
+ @override
+ String get navData => '資料';
+
+ @override
+ String get mapLayerSatelliteBtdWvirw => 'ひまわり 過衝雲頂';
+
+ @override
+ String get meshtasticReadingAge => '數值時間';
+
+ @override
+ String get mapAppCallFailed => '此裝置冇辦法撥打電話';
+
+ @override
+ String get reportFilterAny => '唔限';
+
+ @override
+ String get weatherRankingMergeTo => '合併至';
+
+ @override
+ String get notifyIntensity => '震度速報';
+
+ @override
+ String get rainIntervalMenu => '累積時段';
+
+ @override
+ String get reportDetailLocalFelt => '小區域有感地震';
+
+ @override
+ String get meshtasticDevice => '裝置';
+
+ @override
+ String get onboardingGrant => '授權';
+
+ @override
+ String get weatherModeRain => '雨天';
+
+ @override
+ String get shelterVulnerableOkLabel => '適合避難弱者安置';
+
+ @override
+ String get stationSheetEmpty => '點選任一測站查看觀測值';
+
+ @override
+ String get typhoonLegendProbability => '侵襲機率';
+
+ @override
+ String get reportFilterMagnitude => '規模';
+
+ @override
+ String get skyTimeMorning => '上午';
+
+ @override
+ String get experimentalFeatures => '實驗性功能';
+
+ @override
+ String get onboardingTermsBody =>
+ '使用 DPIP 前,請詳閱以下注意事項:\n\n• 任何資訊應以中央氣象署發布嘅內容為準。\n\n• 根據網絡狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收唔到資訊嘅可能性,我哋會盡力避免此類情況,但唔保證一定唔會發生。\n\n• 強烈搖晃有機會早過通知到達用戶所在地。\n\n• 地震速報係快速計算嘅結果,可能存在較大誤差,應該理解並謹慎使用。\n\n• 任何唔受官方認可嘅行為均有可能承擔法律風險,請務必遵守相關規範。\n\n此外,為提供本地化警報,本服務會喺前景及背景收集並上傳你嘅概略位置同裝置推送識別碼,僅用嚟決定應向你推送嘅警報。\n\n㩒下方「同意並繼續」就表示你已閱讀、理解並同意上述事項。';
+
+ @override
+ String get reportFilterTitle => '篩選';
+
+ @override
+ String get onboardingPermCritical => '重大通知';
+
+ @override
+ String trendCumulativeTotal(String total) {
+ return '累計 $total mm';
+ }
+
+ @override
+ String get languageName => '粵語';
+
+ @override
+ String get reportListEmptyFiltered => '冇符合條件嘅地震報告';
+
+ @override
+ String get meshtasticExcludeMqtt => '隱藏 MQTT 節點';
+
+ @override
+ String get mapNavTyphoon => '颱風';
+
+ @override
+ String get weatherModeSand => '沙塵';
+
+ @override
+ String get notifyReport => '地震報告';
+
+ @override
+ String get mapAppCoordinatesCopied => '已複製座標';
+
+ @override
+ String get skyTimeNight => '夜晚';
+
+ @override
+ String get sponsorRecommended => '推薦';
+
+ @override
+ String get mapLayerSatelliteB15 => 'ひまわり 長波紅外線(B15)';
+
+ @override
+ String get weatherRankingWind => '風速';
+
+ @override
+ String get feedStale => '資料可能已過期';
+
+ @override
+ String homeForecastWind(String direction, String level) {
+ return '$direction · $level 級';
+ }
+
+ @override
+ String get navHome => '主頁';
+
+ @override
+ String get meshtasticRegionLabel => '地區';
+
+ @override
+ String get mapLayerSatelliteCloudtop => 'ひまわり 雲頂溫度';
+
+ @override
+ String get moonTimelineCaption => '月相';
+
+ @override
+ String get openSourceLicenses => '引用套件';
+
+ @override
+ String get weatherRankingLowest => '最低';
+
+ @override
+ String get reportFilterSortDepth => '深度';
+
+ @override
+ String mapTimelineDataTime(String time) {
+ return '資料時間 $time';
+ }
+
+ @override
+ String get radarScanRange => '顯示掃描範圍';
+
+ @override
+ String get meshtasticHopLimit => '跳數上限';
+
+ @override
+ String get weatherRankingExtremeHigh => '今日最高';
+
+ @override
+ String get sponsorPrivacy => '私隱權政策';
+
+ @override
+ String get reportDetailLocalIntensity => '所在地嘅震度';
+
+ @override
+ String get mapLayerSatelliteNaturalcolor => 'ひまわり 自然色';
+
+ @override
+ String get meshtasticAirtime => '發射佔空比';
+
+ @override
+ String shelterCapacityValue(int n) {
+ return '$n 人';
+ }
+
+ @override
+ String lightningLegendCc(int minutes) {
+ return '雲間 · $minutes 分內';
+ }
+
+ @override
+ String get meshtasticSendHint => '要廣播嘅訊息';
+
+ @override
+ String monitorDelay(String value) {
+ return '延遲 $value s';
+ }
+
+ @override
+ String get dpmNo => '否';
+
+ @override
+ String get mapLayerSatelliteB08 => 'ひまわり 上層水氣(B08)';
+
+ @override
+ String get meshtasticReconnecting => '重新連線中…';
+
+ @override
+ String get radarTownOutlineSubtitle => '讓鄉鎮界線在雷達回波下仍然清楚。';
+
+ @override
+ String get typhoonOverlayWeatherSatelliteTooltip => '紅外線(對齊颱風報文時間)';
+
+ @override
+ String get radarScanRangeHint => '框外空白代表未觀測';
+
+ @override
+ String typhoonPickerTd(String no) {
+ return '熱帶性低氣壓 TD $no';
+ }
+
+ @override
+ String get mapLayerSatelliteWatervapor => 'ひまわり 水氣';
+
+ @override
+ String get regionAddButton => '新增地區';
+
+ @override
+ String get displaySettings => '顯示設定';
+
+ @override
+ String get restroomGradePoor => '唔合格';
+
+ @override
+ String get restroomCategoryTourist => '觀光地區及風景區';
+
+ @override
+ String get locationBannerServiceOff => '定位服務已關閉,冇辦法針對你嘅所在地推送警報。';
+
+ @override
+ String get mapLayerStyleTooltip => '顯示樣式';
+
+ @override
+ String lightningLegendCg(int minutes) {
+ return '對地 · $minutes 分內';
+ }
+
+ @override
+ String get skyTimeAuto => '自動';
+
+ @override
+ String get appLogs => 'App 日誌';
+
+ @override
+ String get serverStatusLocal => '本機狀態';
+
+ @override
+ String get serverStatusLocalBody =>
+ '伺服器指標來自控制台。下方係本機對多活端點(LB / Core 各區)嘅實際連線判斷:APP 只被動記錄本機實際播送嘅流量,若該端點從未被本機觸發,就會顯示未探測。';
+
+ @override
+ String get serverStatusAllUp => '所有服務正常';
+
+ @override
+ String get serverStatusDegraded => '服務效能下降';
+
+ @override
+ String get serverStatusDown => '服務異常';
+
+ @override
+ String get serverStatusErrorRate => '5xx 錯誤率';
+
+ @override
+ String get serverStatusLatency => '平均延遲';
+
+ @override
+ String get serverStatusUpdated => '更新於';
+
+ @override
+ String get serverStatusWeb => '伺服器狀態';
+
+ @override
+ String get serverStatusWebUrl => 'status.exptech.dev';
+
+ @override
+ String get serverStatusExpTech => 'ExpTech 狀態';
+
+ @override
+ String get serverStatusCloudflare => 'Cloudflare 狀態';
+
+ @override
+ String get serverStatusCloudflareAllOperational => '所有區域正常';
+
+ @override
+ String get serverStatusCloudflareOutage => 'Cloudflare 部分區域異常';
+
+ @override
+ String get serverStatusCloudflareNone => '而家冇可顯示嘅區域。';
+
+ @override
+ String get serverStatusCloudflareOperational => '正常';
+
+ @override
+ String get serverStatusCloudflareDegraded => '效能下降';
+
+ @override
+ String get serverStatusCloudflarePartial => '部分中斷';
+
+ @override
+ String get serverStatusCloudflareMajor => '大規模中斷';
+
+ @override
+ String get serverStatusCloudflareUnknown => '未知';
+
+ @override
+ String get endpointTierLbApi => 'LB API';
+
+ @override
+ String get endpointTierLbStatic => 'LB Static';
+
+ @override
+ String get endpointTierCoreApi => 'Core API';
+
+ @override
+ String get endpointTierCoreStatic => 'Core Static';
+
+ @override
+ String get endpointTierCoreExclusiveApi => 'Core 專屬 API(雷達 / 氣象 / 風場)';
+
+ @override
+ String get endpointTierCoreStaticExclusive => 'Core 專屬靜態資源';
+
+ @override
+ String get endpointTierLegacyApi => '舊版 API(api-1)';
+
+ @override
+ String get endpointHealthOk => '本機連線正常';
+
+ @override
+ String get endpointHealthDegraded => '有端點連線唔穩';
+
+ @override
+ String get endpointHealthDown => '本機連線異常';
+
+ @override
+ String get endpointHealthUnknown => '尚無觀測資料';
+
+ @override
+ String get endpointStateOk => '正常';
+
+ @override
+ String get endpointStateDegraded => '唔穩';
+
+ @override
+ String get endpointStateDown => '異常';
+
+ @override
+ String get endpointStateUnknown => '未知';
+
+ @override
+ String get endpointServiceEew => '地震速報';
+
+ @override
+ String get endpointServiceRts => '強震即時警報';
+
+ @override
+ String get endpointServiceRadar => '雷達';
+
+ @override
+ String get endpointServiceSatellite => '衛星';
+
+ @override
+ String get endpointServiceQpesums => '定量降水';
+
+ @override
+ String get endpointServiceWind => '風場';
+
+ @override
+ String get endpointServiceDpm => '災害點位';
+
+ @override
+ String get endpointServiceWeather => '天氣';
+
+ @override
+ String get endpointServiceRain => '降雨';
+
+ @override
+ String get endpointServiceLightning => '閃電';
+
+ @override
+ String get endpointServiceTyphoon => '颱風';
+
+ @override
+ String get endpointServiceReport => '地震報告';
+
+ @override
+ String get endpointServiceTremStation => '震度站';
+
+ @override
+ String get endpointServiceEvent => '事件';
+
+ @override
+ String get endpointServiceLocation => '定位';
+
+ @override
+ String get endpointServiceNotify => '通知';
+
+ @override
+ String get endpointServiceOther => '其他';
+
+ @override
+ String get feedConnecting => '連接中…';
+
+ @override
+ String get notifyBannerDisabled => '通知已關閉,將收唔到災害警報。';
+
+ @override
+ String get weatherHumidity => '濕度';
+
+ @override
+ String typhoonValueMs(String n) {
+ return '每秒 $n 公尺';
+ }
+
+ @override
+ String homeForecastHumidity(String value) {
+ return '濕度 $value%';
+ }
+
+ @override
+ String get meshtasticBusyBody =>
+ '請先喺另一個 Meshtastic App 中斷線。兩個 App 同時連同一台裝置會互相搶走訊息,導致部分訊息遺失。';
+
+ @override
+ String get meshtasticChannelNoSlot => '冇可用嘅頻道空位 — 請先喺裝置上空出一個';
+
+ @override
+ String get restroomCategoryTransport => '交通';
+
+ @override
+ String get meshtasticBattery => '電量';
+
+ @override
+ String get meshtasticDistance => '距離';
+
+ @override
+ String get meshtasticSnrTrend => '訊號趨勢 (SNR)';
+
+ @override
+ String get meshtasticBatteryTrend => '電量趨勢';
+
+ @override
+ String get typhoonOverlayMenuTooltip => '颱風圖層選項';
+
+ @override
+ String get mapLayerSatelliteBtdOzone => 'ひまわり 對流層頂';
+
+ @override
+ String meshtasticRegionMismatch(String region) {
+ return '裝置地區為 $region — DPIP 需要 TW';
+ }
+
+ @override
+ String get notifySectionEarthquake => '地震';
+
+ @override
+ String get mapLayerDisasterMap => '防災地圖';
+
+ @override
+ String get weatherModeFog => '大霧';
+
+ @override
+ String typhoonPickerNamed(String no, String name) {
+ return '$name TY $no';
+ }
+
+ @override
+ String get mapLayerStyleGrayTooltip => '氣象廳灰階慣例:溫度越低越白';
+
+ @override
+ String get moreAnnouncements => '公告';
+
+ @override
+ String get moreTagline => '防災資訊整合平台';
+
+ @override
+ String get moreVersionStable => '正式版';
+
+ @override
+ String get moreVersionNotes => '本次更新';
+
+ @override
+ String get moreVersionNotesHighlightsSubtitle => '呢個版本做咗哪些改變';
+
+ @override
+ String releaseHighlightsTitle(Object train) {
+ return '$train 重點整理';
+ }
+
+ @override
+ String get releaseHighlightsTabNormal => '做咗哪些改變';
+
+ @override
+ String get releaseHighlightsTabAdvanced => '深入技術';
+
+ @override
+ String get releaseHighlightsEmpty => '而家冇內容。';
+
+ @override
+ String get releaseHighlightsSeeNotes => '查看完整更新日誌';
+
+ @override
+ String get moreVersionNotesEmpty => '找唔到而家版本嘅更新日誌';
+
+ @override
+ String get moreVersionSnapshot => '測試版';
+
+ @override
+ String get mapLayerSatelliteTransparentNoData => '無資料(陸地) = 透明';
+
+ @override
+ String get restroomCategoryGovernment => '民眾洽公場所';
+
+ @override
+ String get typhoonLegendCurrent => '而家中心';
+
+ @override
+ String get aedAddress => '地址';
+
+ @override
+ String get mapLayerAed => 'AED';
+
+ @override
+ String get changelogTypePrerelease => '測試版';
+
+ @override
+ String get reportFilterIntensityInfoModernBody =>
+ '震度為 0–4、5弱、5強、6弱、6強、7。篩選滑桿依新制;列表中較早嘅地震會以舊制標示顯示。';
+
+ @override
+ String get typhoonOverlayWeatherNone => '無';
+
+ @override
+ String get mapLayerStyleGray => '灰階(JMA)';
+
+ @override
+ String get weatherModeAuto => '自動';
+
+ @override
+ String get typhoonLabelProbCircle => '70%機率圓';
+
+ @override
+ String get notifyOptAll => '接收全部';
+
+ @override
+ String get displayTheme => '主題';
+
+ @override
+ String get mapLayerSatelliteB07 => 'ひまわり 短波紅外(B07)';
+
+ @override
+ String get typhoonLabelDirection => '過去移動方向';
+
+ @override
+ String get regionManageTitle => '常用地區';
+
+ @override
+ String get regionSaveNote =>
+ '通知係以 GPS 所在地位置發送嘅,設定常用地區唔會改變或影響通知發送,常用地區只係用於首頁快速查看唔同區域狀態,所以務必授予 GPS 定位權限,否則通知冇辦法運作';
+
+ @override
+ String get typhoonLegendCone => '預測圓錐';
+
+ @override
+ String get moreCwaEew => '中央氣象署強震即時警報';
+
+ @override
+ String get onboardingPermsTitle => '權限授權';
+
+ @override
+ String get mapLayerStyleJma => '雲頂強調(JMA)';
+
+ @override
+ String get rainInterval10m => '10 分';
+
+ @override
+ String get meshtasticConnectAnyway => '仍要連線';
+
+ @override
+ String reportListDayCount(int count) {
+ return '$count';
+ }
+
+ @override
+ String get mapLayerSatelliteB06 => 'ひまわり 近紅外(B06)';
+
+ @override
+ String get mapLayerSatelliteTransparentReflectance => '低反射率/夜間 = 透明,顯示底圖';
+
+ @override
+ String chartHourLabel(int hour) {
+ return '$hour時';
+ }
+
+ @override
+ String get mapLayerShelter => '避難收容場所';
+
+ @override
+ String get typhoonOverlayProbabilityTooltip => '顯示侵襲機率(會隱藏預測圓錐)';
+
+ @override
+ String get mapLayerSatelliteNdwi => 'ひまわり 水體指數';
+
+ @override
+ String get disasterMapOverlayShelterTooltip => '顯示避難收容場所';
+
+ @override
+ String get mapNavHumidity => '濕度';
+
+ @override
+ String get reportDetailSortByIntensity => '依震度排序';
+
+ @override
+ String get homeRainTrendNoData => '無資料';
+
+ @override
+ String get mapLayerCategoryRadar => '雷達';
+
+ @override
+ String get meshtasticShortName => '簡稱';
+
+ @override
+ String get mapLayerSatelliteAirmass => 'ひまわり 氣團';
+
+ @override
+ String get dataSectionWeather => '氣象';
+
+ @override
+ String get aedHoursWeekday => '平日開放時間';
+
+ @override
+ String get homeActiveEventsTitle => '生效中事件';
+
+ @override
+ String get faq => '常見問題';
+
+ @override
+ String eewSerial(int serial) {
+ return '第 $serial 報';
+ }
+
+ @override
+ String get reportFilterSort => '排序方式';
+
+ @override
+ String get meshtasticRegionConfirm =>
+ '要將呢台裝置切換為 TW 地區嗎?裝置會重新啟動並短暫斷線,上面嘅其他頻道都會一齊改變。';
+
+ @override
+ String get dataEarthquakeSubtitle => '地震報告';
+
+ @override
+ String get typhoonNoActive => '而家無颱風';
+
+ @override
+ String get mapLayerSatelliteB11 => 'ひまわり 二氧化硫/雲相(B11)';
+
+ @override
+ String get navEvents => '事件';
+
+ @override
+ String get onboardingTermsTitle => '服務條款';
+
+ @override
+ String get mapOsmOverlay => '詳細地圖';
+
+ @override
+ String get mapOsmOverlayHint => '顯示更完整嘅道路、建物同地名';
+
+ @override
+ String get mapOsmDetails => '詳細設定';
+
+ @override
+ String get moreDataSources => '資料來源';
+
+ @override
+ String get dataSourceTremNet => '探索智慧科技有限公司 — TREM-Net';
+
+ @override
+ String get dataSourceCwa => '交通部中央氣象署 (CWA)';
+
+ @override
+ String get dataSourceJma => '気象庁 (JMA)';
+
+ @override
+ String get dataSourceNcdr => '國家災害防救科技中心 (NCDR)';
+
+ @override
+ String get dataSourceEcmwf =>
+ 'European Centre for Medium-Range Weather Forecasts (ECMWF)';
+
+ @override
+ String get dataSourceNoaaGfs =>
+ 'National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)';
+
+ @override
+ String get dataSourceGovernmentOpenData => '政府資料開放平臺';
+
+ @override
+ String get dataSourceOpenStreetMap => '© OpenStreetMap contributors';
+
+ @override
+ String get dataSourceNasaMoon =>
+ 'National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)';
+
+ @override
+ String mapOsmDetailsHint(int enabled, int total) {
+ return '已啟用 $enabled / 共 $total 個圖層';
+ }
+
+ @override
+ String get mapOsmSurface => '地表';
+
+ @override
+ String get mapOsmParks => '公園';
+
+ @override
+ String get mapOsmLandUse => '土地利用';
+
+ @override
+ String get mapOsmAirportAreas => '機場區域';
+
+ @override
+ String get mapOsmWater => '水域';
+
+ @override
+ String get mapOsmRivers => '河川';
+
+ @override
+ String get mapOsmBoundaries => '邊界';
+
+ @override
+ String get mapOsmBuildings => '建物';
+
+ @override
+ String get mapOsmRoads => '道路';
+
+ @override
+ String get mapOsmRoadNames => '道路名稱';
+
+ @override
+ String get mapOsmWaterNames => '水域名稱';
+
+ @override
+ String get mapOsmPeaks => '山峰';
+
+ @override
+ String get mapOsmAirportNames => '機場名稱';
+
+ @override
+ String get mapOsmPlaceNames => '地名';
+
+ @override
+ String get mapOsmPoi => '地標';
+
+ @override
+ String get mapOsmHouseNumbers => '門牌號碼';
+
+ @override
+ String get mapOsmRestoreAll => '全部恢復';
+
+ @override
+ String get mapOsmSectionNatural => '地表同自然';
+
+ @override
+ String get mapOsmSectionRoadsAndBuildings => '道路同建物';
+
+ @override
+ String get mapOsmSectionLabelsAndPlaces => '地名同標示';
+
+ @override
+ String get mapTownLabels => '鄉鎮名稱';
+
+ @override
+ String get notifySetFailed => '設定失敗,請稍後再試。';
+
+ @override
+ String get meshtasticDisconnect => '斷線';
+
+ @override
+ String get meshtasticUndecoded => '冇辦法解密';
+
+ @override
+ String get notifyAnnouncement => '公告';
+
+ @override
+ String get onboardingIntroTitle => '歡迎使用 DPIP';
+
+ @override
+ String get regionCurrentUnavailable => '冇辦法取得所在地位置資訊';
+
+ @override
+ String get languageSystem => '系統預設';
+
+ @override
+ String get skyTimeSunset => '日落';
+
+ @override
+ String get mapLayerSatelliteDust => 'ひまわり 沙塵';
+
+ @override
+ String get mapAppAppleMaps => 'Apple Maps';
+
+ @override
+ String get regionEdit => '修改';
+
+ @override
+ String get weatherDynamicState => '天氣動態狀態';
+
+ @override
+ String get moonNow => '而家';
+
+ @override
+ String get moonSectionAppearance => '外觀';
+
+ @override
+ String get moonSectionRiseSet => '月出月落';
+
+ @override
+ String get moonSectionUpcoming => '接下來';
+
+ @override
+ String get moonSectionCalendar => '月曆';
+
+ @override
+ String get moonDistance => '距離';
+
+ @override
+ String get moonKilometres => '公里';
+
+ @override
+ String get moonApparentSize => '視直徑';
+
+ @override
+ String get moonRise => '月出';
+
+ @override
+ String get moonSet => '月落';
+
+ @override
+ String get moonNextNewMoon => '下次新月';
+
+ @override
+ String get moonAlwaysUp => '整日在地平線上';
+
+ @override
+ String get moonNoEvent => '當日無';
+
+ @override
+ String get sunTitle => '太陽';
+
+ @override
+ String get sunSectionDaylight => '日照';
+
+ @override
+ String get sunSectionTwilight => '曙暮光';
+
+ @override
+ String get sunSectionLight => '光線';
+
+ @override
+ String get sunSectionSundial => '日晷';
+
+ @override
+ String get sunSectionTerms => '節氣';
+
+ @override
+ String get sunRise => '日出';
+
+ @override
+ String get sunSet => '日冇';
+
+ @override
+ String get sunNoon => '正午';
+
+ @override
+ String get sunDayLength => '白晝長度';
+
+ @override
+ String get sunTwilightCivil => '民用';
+
+ @override
+ String get sunTwilightNautical => '航海';
+
+ @override
+ String get sunTwilightAstronomical => '天文';
+
+ @override
+ String get sunGoldenHourMorning => '晨間黃金時刻';
+
+ @override
+ String get sunGoldenHourEvening => '昏間黃金時刻';
+
+ @override
+ String get sunBlueHour => '藍調時刻';
+
+ @override
+ String get sunEquationOfTime => '均時差';
+
+ @override
+ String get sunMinutes => '分';
+
+ @override
+ String get solarTermNext => '下一個節氣';
+
+ @override
+ String get planetsTitle => '行星';
+
+ @override
+ String get planetsSectionTonight => '此刻';
+
+ @override
+ String get planetUp => '地平線上';
+
+ @override
+ String get planetDown => '地平線下';
+
+ @override
+ String get planetInGlare => '太近太陽';
+
+ @override
+ String get planetMagnitude => '亮度';
+
+ @override
+ String get planetElongation => '距日距角';
+
+ @override
+ String get planetSky => '時段';
+
+ @override
+ String get planetEvening => '昏星';
+
+ @override
+ String get planetMorning => '晨星';
+
+ @override
+ String get planetDistance => '距離';
+
+ @override
+ String get planetAu => '天文單位';
+
+ @override
+ String get planetAltitude => '仰角';
+
+ @override
+ String get planetMercury => '水星';
+
+ @override
+ String get planetVenus => '金星';
+
+ @override
+ String get planetMars => '火星';
+
+ @override
+ String get planetJupiter => '木星';
+
+ @override
+ String get planetSaturn => '土星';
+
+ @override
+ String get planetUranus => '天王星';
+
+ @override
+ String get planetNeptune => '海王星';
+
+ @override
+ String get solarTermVernalEquinox => '春分';
+
+ @override
+ String get solarTermPureBrightness => '清明';
+
+ @override
+ String get solarTermGrainRain => '穀雨';
+
+ @override
+ String get solarTermStartOfSummer => '立夏';
+
+ @override
+ String get solarTermGrainFull => '小滿';
+
+ @override
+ String get solarTermGrainInEar => '芒種';
+
+ @override
+ String get solarTermSummerSolstice => '夏至';
+
+ @override
+ String get solarTermMinorHeat => '小暑';
+
+ @override
+ String get solarTermMajorHeat => '大暑';
+
+ @override
+ String get solarTermStartOfAutumn => '立秋';
+
+ @override
+ String get solarTermEndOfHeat => '處暑';
+
+ @override
+ String get solarTermWhiteDew => '白露';
+
+ @override
+ String get solarTermAutumnalEquinox => '秋分';
+
+ @override
+ String get solarTermColdDew => '寒露';
+
+ @override
+ String get solarTermFrostDescent => '霜降';
+
+ @override
+ String get solarTermStartOfWinter => '立冬';
+
+ @override
+ String get solarTermMinorSnow => '小雪';
+
+ @override
+ String get solarTermMajorSnow => '大雪';
+
+ @override
+ String get solarTermWinterSolstice => '冬至';
+
+ @override
+ String get solarTermMinorCold => '小寒';
+
+ @override
+ String get solarTermMajorCold => '大寒';
+
+ @override
+ String get solarTermStartOfSpring => '立春';
+
+ @override
+ String get solarTermRainWater => '雨水';
+
+ @override
+ String get solarTermAwakeningOfInsects => '驚蟄';
+
+ @override
+ String get tonightTitle => '今夜';
+
+ @override
+ String get tonightSectionDark => '觀測窗口';
+
+ @override
+ String get tonightAstronomicalNight => '天文夜';
+
+ @override
+ String get tonightNeverDark => '整夜唔全暗';
+
+ @override
+ String get tonightDarkWindow => '暗窗';
+
+ @override
+ String get tonightMoonAllNight => '月亮整夜喺天上';
+
+ @override
+ String get tonightDarkTotal => '總暗時';
+
+ @override
+ String get tonightMoonlight => '月光';
+
+ @override
+ String get tonightSectionShowers => '流星雨';
+
+ @override
+ String get tonightRadiantDown => '輻射點唔升起';
+
+ @override
+ String get tonightPerHour => '顆/時';
+
+ @override
+ String get tonightSectionSatellites => '衛星過境';
+
+ @override
+ String get tonightSectionTargets => '此刻可觀測目標';
+
+ @override
+ String get showerQuadrantids => '象限儀座';
+
+ @override
+ String get showerLyrids => '天琴座';
+
+ @override
+ String get showerEtaAquariids => '寶瓶座η';
+
+ @override
+ String get showerDeltaAquariids => '寶瓶座δ';
+
+ @override
+ String get showerPerseids => '英仙座';
+
+ @override
+ String get showerOrionids => '獵戶座';
+
+ @override
+ String get showerSouthernTaurids => '金牛座南';
+
+ @override
+ String get showerLeonids => '獅子座';
+
+ @override
+ String get showerGeminids => '雙子座';
+
+ @override
+ String get showerUrsids => '小熊座';
+
+ @override
+ String get deepSkyOpenCluster => '疏散星團';
+
+ @override
+ String get deepSkyGlobularCluster => '球狀星團';
+
+ @override
+ String get deepSkySpiralGalaxy => '螺旋星系';
+
+ @override
+ String get deepSkyEllipticalGalaxy => '橢圓星系';
+
+ @override
+ String get deepSkyIrregularGalaxy => '唔規則星系';
+
+ @override
+ String get deepSkyPlanetaryNebula => '行星狀星雲';
+
+ @override
+ String get deepSkySupernovaRemnant => '超新星遺跡';
+
+ @override
+ String get deepSkyEmissionNebula => '發射星雲';
+
+ @override
+ String get deepSkyReflectionNebula => '反射星雲';
+
+ @override
+ String get deepSkyAsterism => '星群';
+
+ @override
+ String get almanacTitle => '曆法';
+
+ @override
+ String get almanacSectionToday => '今日';
+
+ @override
+ String get almanacGregorian => '西曆';
+
+ @override
+ String get almanacLunar => '農曆';
+
+ @override
+ String get almanacYear => '歲次';
+
+ @override
+ String get almanacMonthLength => '月大小';
+
+ @override
+ String get almanacLongMonth => '三十日';
+
+ @override
+ String get almanacShortMonth => '二十九日';
+
+ @override
+ String get almanacLeapPrefix => '閏';
+
+ @override
+ String get almanacSectionLunarEclipses => '月食';
+
+ @override
+ String get almanacSectionSolarEclipses => '日食';
+
+ @override
+ String get almanacNoSolarEclipse => '範圍內無';
+
+ @override
+ String get eclipseTotal => '全食';
+
+ @override
+ String get eclipsePartial => '偏食';
+
+ @override
+ String get eclipseAnnular => '環食';
+
+ @override
+ String get eclipsePenumbral => '半影食';
+
+ @override
+ String get zodiacRat => '鼠';
+
+ @override
+ String get zodiacOx => '牛';
+
+ @override
+ String get zodiacTiger => '虎';
+
+ @override
+ String get zodiacRabbit => '兔';
+
+ @override
+ String get zodiacDragon => '龍';
+
+ @override
+ String get zodiacSnake => '蛇';
+
+ @override
+ String get zodiacHorse => '馬';
+
+ @override
+ String get zodiacGoat => '羊';
+
+ @override
+ String get zodiacMonkey => '猴';
+
+ @override
+ String get zodiacRooster => '雞';
+
+ @override
+ String get zodiacDog => '狗';
+
+ @override
+ String get zodiacPig => '豬';
+
+ @override
+ String get tideTitle => '潮汐';
+
+ @override
+ String get tideDisclaimer => '僅為天文引潮力,非港口潮汐表。水位請參考氣象署公布嘅潮汐預報。';
+
+ @override
+ String get tideSectionNow => '此刻';
+
+ @override
+ String get tidePhase => '週期';
+
+ @override
+ String get tideSpring => '大潮';
+
+ @override
+ String get tideNeap => '小潮';
+
+ @override
+ String get tideMiddling => '中潮';
+
+ @override
+ String get tideLunarDistanceFactor => '月球引力';
+
+ @override
+ String get tideEquilibrium => '平衡潮高';
+
+ @override
+ String get tideMetres => '公尺';
+
+ @override
+ String get tidePerigeanSpring => '下次近地點大潮';
+
+ @override
+ String get tideSectionTurningPoints => '轉折點';
+
+ @override
+ String get tideHigh => '高';
+
+ @override
+ String get tideLow => '低';
+
+ @override
+ String get skyChartTitle => '星圖';
+
+ @override
+ String get skyChartNorth => '北';
+
+ @override
+ String get skyChartEast => '東';
+
+ @override
+ String get skyChartSouth => '南';
+
+ @override
+ String get skyChartWest => '西';
+
+ @override
+ String tonightElementAge(int days) {
+ return '軌道資料 $days 天前';
+ }
+
+ @override
+ String almanacLunarDate(String leap, int month, int day) {
+ return '$leap$month 月 $day 日';
+ }
+
+ @override
+ String get tonightNoShowers => '而家無流星雨';
+
+ @override
+ String get tonightNoPasses => '48 小時內無可見過境';
+
+ @override
+ String get tonightSatellitesUnavailable => '冇辦法讀取軌道資料';
+
+ @override
+ String get tonightNoTargets => '無足夠高度嘅目標';
+
+ @override
+ String get skyChartUnavailable => '冇辦法讀取星表';
+
+ @override
+ String get permissionSettingsTitle => '請到系統設定開啟';
+
+ @override
+ String get permissionSettingsHint => '返回 App 後會自動重新檢查。';
+
+ @override
+ String get permissionOpenSettings => '前往設定';
+
+ @override
+ String permissionSettingsMessage(String what) {
+ return '「$what」已被拒絕,系統唔會再詢問。請到設定中開啟。';
+ }
+
+ @override
+ String get permissionGuideNotification => '請到系統設定中開啟通知權限。';
+
+ @override
+ String get permissionGuideForegroundLocation => '請到系統設定中開啟精確位置權限。';
+
+ @override
+ String permissionGuideBackgroundLocation(Object option) {
+ return '請喺「$option」中改為「允許所有時間」。';
+ }
+
+ @override
+ String get permissionGuideBackgroundExecution =>
+ '請到系統設定中允許背景執行,避免收到通知時被系統暫停。';
+
+ @override
+ String get permissionGuideUnusedPause => '若應用程式被標記為「未使用」,請喺系統設定中改為「允許」。';
+
+ @override
+ String get permissionGuideUnusedFreeSpace => '若應用程式因暫存空間唔夠被暫停,請清除暫存後重新開啟。';
+
+ @override
+ String get permissionGuideUnusedRevoke => '若應用程式權限被撤銷,請喺系統設定中重新授予。';
+
+ @override
+ String get permissionGuideUnusedPlayProtect =>
+ '若被 Play 保護機制暫停,請到 Google Play 中檢查應用程式狀態。';
+
+ @override
+ String permissionGuideVendorPower(Object vendor) {
+ return '請到「$vendor」嘅省電設定中,將本應用程式設為「唔限制」。';
+ }
+
+ @override
+ String get permissionStillRequired => '仍然需要此權限,請到設定中開啟。';
+
+ @override
+ String get permissionVerifyManually => '請手動確認此權限已喺系統設定中開啟。';
+
+ @override
+ String get permissionBackgroundLocationOption => '「允許所有時間」';
+
+ @override
+ String get displayTextSize => '文字大小';
+
+ @override
+ String get displayTextSizeDesc => '只調整 App 介面嘅文字,地圖上嘅文字維持原本大小。';
+
+ @override
+ String get displayTextWeight => '文字粗細';
+
+ @override
+ String get displayTextWeightDesc => '文字較粗時可能更容易閱讀。';
+
+ @override
+ String get displayContrast => '對比度';
+
+ @override
+ String get displayContrastDesc => '對比越高,文字同背景越分明。';
+
+ @override
+ String get displayColorVision => '色覺調整';
+
+ @override
+ String get displayColorVisionDesc => '整個 App 嘅顏色都會一併調整,包括地圖。';
+
+ @override
+ String get displayColorVisionNone => '標準';
+
+ @override
+ String get displayColorVisionProtan => '紅色弱';
+
+ @override
+ String get displayColorVisionDeutan => '綠色弱';
+
+ @override
+ String get displayColorVisionTritan => '藍黃色弱';
+
+ @override
+ String get displayPreviewSample => '地震報告範例';
+
+ @override
+ String get displayScaleSmall => '小';
+
+ @override
+ String get displayScaleDefault => '預設';
+
+ @override
+ String get displayScaleLarge => '大';
+
+ @override
+ String get displayScaleHuge => '特大';
+
+ @override
+ String get displayWeightNormal => '一般';
+
+ @override
+ String get displayWeightMedium => '中等';
+
+ @override
+ String get displayWeightBold => '粗體';
+
+ @override
+ String get displayContrastStandard => '標準';
+
+ @override
+ String get displayContrastMedium => '中等';
+
+ @override
+ String get displayContrastHigh => '高';
+
+ @override
+ String get meshtasticDirect => '直連';
+
+ @override
+ String meshtasticHopsAway(int n) {
+ return '$n 跳';
+ }
+
+ @override
+ String get meshtasticStatRelayShare => '為他人轉發';
+
+ @override
+ String get meshtasticStatRelayShareHint => '佔本機發送量嘅比例';
+
+ @override
+ String get meshtasticStatRelayValue => '轉發成功率';
+
+ @override
+ String get meshtasticStatRelaySolePath => '經常係唯一路徑 — 網絡依賴此節點';
+
+ @override
+ String get meshtasticStatRelayRedundant => '其他節點都覆蓋同樣路徑';
+
+ @override
+ String get meshtasticStatRedundancy => '重複接收';
+
+ @override
+ String get meshtasticStatThinEdge => '備援路徑少 — 一個中繼失效就可能斷線';
+
+ @override
+ String get meshtasticStatWellCovered => '有多條路徑可達';
+
+ @override
+ String get meshtasticStatErrorRate => '接收錯誤率';
+
+ @override
+ String get meshtasticStatErrorRateHint => '空中時間唔變卻升高 = 干擾';
+
+ @override
+ String get meshtasticTraceRoute => '追蹤路由';
+
+ @override
+ String get meshtasticTracing => '追蹤中…';
+
+ @override
+ String get meshtasticTraceUnreadable => '冇辦法解讀嘅回覆';
+
+ @override
+ String get meshtasticTraceOffline => '未連線至電台';
+
+ @override
+ String get meshtasticTraceCooldown => '電台限制每 30 秒一次';
+
+ @override
+ String get meshtasticTraceNoReply => '冇回應 — 超出範圍或金鑰唔同';
+
+ @override
+ String get meshtasticTraceDirect => '直達 — 中間無中繼';
+
+ @override
+ String meshtasticTraceHops(int n) {
+ return '$n 跳';
+ }
+
+ @override
+ String get moreDumpDiagnostics => '傾印除錯資訊及日誌';
+
+ @override
+ String get moreDumpDiagnosticsHint => '上載後複製連結';
+
+ @override
+ String get dumpIncludeSensitive => '包含精確位置';
+
+ @override
+ String get dumpIncludeSensitiveHint => '包含日誌同背景定位入面嘅座標;唔勾選就會以 null 取代';
+
+ @override
+ String get dumpUpload => '上載';
+
+ @override
+ String get dumpUploaded => '已上載';
+
+ @override
+ String get dumpLinkCopied => '連結已複製到剪貼簿';
+
+ @override
+ String get dumpCopyAgain => '再複製一次';
+
+ @override
+ String get dumpUploadFailed => '上載失敗,請稍後再試';
+
+ @override
+ String get statusLegendUnprobed => '未探測';
+
+ @override
+ String get statusLegendUnsupported => '唔支援';
+}
diff --git a/lib/l10n/gen/app_localizations_zh.dart b/lib/l10n/gen/app_localizations_zh.dart
index e52ae7dc0..223efb74e 100644
--- a/lib/l10n/gen/app_localizations_zh.dart
+++ b/lib/l10n/gen/app_localizations_zh.dart
@@ -2082,10 +2082,15 @@ class AppLocalizationsZh extends AppLocalizations {
String get moreVersionStable => '正式版';
@override
- String get moreVersionNotes => '目前版本';
+ String get moreVersionNotes => '本次更新';
@override
- String get releaseHighlightsTitle => '本次更新';
+ String get moreVersionNotesHighlightsSubtitle => '這個版本做了哪些改變';
+
+ @override
+ String releaseHighlightsTitle(Object train) {
+ return '$train 重點整理';
+ }
@override
String get releaseHighlightsTabNormal => '做了哪些改變';
@@ -2261,6 +2266,113 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String get onboardingTermsTitle => '服務條款';
+ @override
+ String get mapOsmOverlay => '詳細地圖';
+
+ @override
+ String get mapOsmOverlayHint => '顯示更完整的道路、建物與地名';
+
+ @override
+ String get mapOsmDetails => '詳細設定';
+
+ @override
+ String get moreDataSources => '資料來源';
+
+ @override
+ String get dataSourceTremNet => '探索智慧科技有限公司 — TREM-Net';
+
+ @override
+ String get dataSourceCwa => '交通部中央氣象署 (CWA)';
+
+ @override
+ String get dataSourceJma => '気象庁 (JMA)';
+
+ @override
+ String get dataSourceNcdr => '國家災害防救科技中心 (NCDR)';
+
+ @override
+ String get dataSourceEcmwf =>
+ 'European Centre for Medium-Range Weather Forecasts (ECMWF)';
+
+ @override
+ String get dataSourceNoaaGfs =>
+ 'National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)';
+
+ @override
+ String get dataSourceGovernmentOpenData => '政府資料開放平臺';
+
+ @override
+ String get dataSourceOpenStreetMap => '© OpenStreetMap contributors';
+
+ @override
+ String get dataSourceNasaMoon =>
+ 'National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)';
+
+ @override
+ String mapOsmDetailsHint(int enabled, int total) {
+ return '已啟用 $enabled / 共 $total 個圖層';
+ }
+
+ @override
+ String get mapOsmSurface => '地表';
+
+ @override
+ String get mapOsmParks => '公園';
+
+ @override
+ String get mapOsmLandUse => '土地利用';
+
+ @override
+ String get mapOsmAirportAreas => '機場區域';
+
+ @override
+ String get mapOsmWater => '水域';
+
+ @override
+ String get mapOsmRivers => '河川';
+
+ @override
+ String get mapOsmBoundaries => '邊界';
+
+ @override
+ String get mapOsmBuildings => '建物';
+
+ @override
+ String get mapOsmRoads => '道路';
+
+ @override
+ String get mapOsmRoadNames => '道路名稱';
+
+ @override
+ String get mapOsmWaterNames => '水域名稱';
+
+ @override
+ String get mapOsmPeaks => '山峰';
+
+ @override
+ String get mapOsmAirportNames => '機場名稱';
+
+ @override
+ String get mapOsmPlaceNames => '地名';
+
+ @override
+ String get mapOsmPoi => '地標';
+
+ @override
+ String get mapOsmHouseNumbers => '門牌號碼';
+
+ @override
+ String get mapOsmRestoreAll => '全部恢復';
+
+ @override
+ String get mapOsmSectionNatural => '地表與自然';
+
+ @override
+ String get mapOsmSectionRoadsAndBuildings => '道路與建物';
+
+ @override
+ String get mapOsmSectionLabelsAndPlaces => '地名與標示';
+
@override
String get mapTownLabels => '鄉鎮名稱';
@@ -2807,6 +2919,48 @@ class AppLocalizationsZh extends AppLocalizations {
return '「$what」已被拒絕,系統不會再詢問。請到設定中開啟。';
}
+ @override
+ String get permissionGuideNotification => '請到系統設定中開啟通知權限。';
+
+ @override
+ String get permissionGuideForegroundLocation => '請到系統設定中開啟精確位置權限。';
+
+ @override
+ String permissionGuideBackgroundLocation(Object option) {
+ return '請在「$option」中改為「允許所有時間」。';
+ }
+
+ @override
+ String get permissionGuideBackgroundExecution =>
+ '請到系統設定中允許背景執行,避免收到通知時被系統暫停。';
+
+ @override
+ String get permissionGuideUnusedPause => '若應用程式被標記為「未使用」,請在系統設定中改為「允許」。';
+
+ @override
+ String get permissionGuideUnusedFreeSpace => '若應用程式因暫存空間不足被暫停,請清除暫存後重新開啟。';
+
+ @override
+ String get permissionGuideUnusedRevoke => '若應用程式權限被撤銷,請在系統設定中重新授予。';
+
+ @override
+ String get permissionGuideUnusedPlayProtect =>
+ '若被 Play 保護機制暫停,請到 Google Play 中檢查應用程式狀態。';
+
+ @override
+ String permissionGuideVendorPower(Object vendor) {
+ return '請到「$vendor」的省電設定中,將本應用程式設為「不限制」。';
+ }
+
+ @override
+ String get permissionStillRequired => '仍然需要此權限,請到設定中開啟。';
+
+ @override
+ String get permissionVerifyManually => '請手動確認此權限已在系統設定中開啟。';
+
+ @override
+ String get permissionBackgroundLocationOption => '「允許所有時間」';
+
@override
String get displayTextSize => '文字大小';
@@ -2946,6 +3100,15 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String get moreDumpDiagnosticsHint => '上傳後複製連結';
+ @override
+ String get dumpIncludeSensitive => '包含精確位置';
+
+ @override
+ String get dumpIncludeSensitiveHint => '包含日誌與背景定位中的座標;未勾選時會以 null 取代';
+
+ @override
+ String get dumpUpload => '上傳';
+
@override
String get dumpUploaded => '已上傳';
@@ -5042,10 +5205,15 @@ class AppLocalizationsZhHans extends AppLocalizationsZh {
String get moreVersionStable => '正式版';
@override
- String get moreVersionNotes => '当前版本';
+ String get moreVersionNotes => '本次更新';
@override
- String get releaseHighlightsTitle => '本次更新';
+ String get moreVersionNotesHighlightsSubtitle => '这个版本做了哪些改变';
+
+ @override
+ String releaseHighlightsTitle(Object train) {
+ return '$train 重点整理';
+ }
@override
String get releaseHighlightsTabNormal => '做了哪些改变';
@@ -5221,6 +5389,113 @@ class AppLocalizationsZhHans extends AppLocalizationsZh {
@override
String get onboardingTermsTitle => '服务条款';
+ @override
+ String get mapOsmOverlay => '详细地图';
+
+ @override
+ String get mapOsmOverlayHint => '显示更完整的道路、建筑和地名';
+
+ @override
+ String get mapOsmDetails => '详细设置';
+
+ @override
+ String get moreDataSources => '数据来源';
+
+ @override
+ String get dataSourceTremNet => '探索智慧科技有限公司 — TREM-Net';
+
+ @override
+ String get dataSourceCwa => '交通部中央氣象署 (CWA)';
+
+ @override
+ String get dataSourceJma => '気象庁 (JMA)';
+
+ @override
+ String get dataSourceNcdr => '國家災害防救科技中心 (NCDR)';
+
+ @override
+ String get dataSourceEcmwf =>
+ 'European Centre for Medium-Range Weather Forecasts (ECMWF)';
+
+ @override
+ String get dataSourceNoaaGfs =>
+ 'National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)';
+
+ @override
+ String get dataSourceGovernmentOpenData => '政府資料開放平臺';
+
+ @override
+ String get dataSourceOpenStreetMap => '© OpenStreetMap contributors';
+
+ @override
+ String get dataSourceNasaMoon =>
+ 'National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)';
+
+ @override
+ String mapOsmDetailsHint(int enabled, int total) {
+ return '已启用 $enabled / 共 $total 个图层';
+ }
+
+ @override
+ String get mapOsmSurface => '地表';
+
+ @override
+ String get mapOsmParks => '公园';
+
+ @override
+ String get mapOsmLandUse => '土地利用';
+
+ @override
+ String get mapOsmAirportAreas => '机场区域';
+
+ @override
+ String get mapOsmWater => '水域';
+
+ @override
+ String get mapOsmRivers => '河川';
+
+ @override
+ String get mapOsmBoundaries => '边界';
+
+ @override
+ String get mapOsmBuildings => '建筑物';
+
+ @override
+ String get mapOsmRoads => '道路';
+
+ @override
+ String get mapOsmRoadNames => '道路名称';
+
+ @override
+ String get mapOsmWaterNames => '水域名称';
+
+ @override
+ String get mapOsmPeaks => '山峰';
+
+ @override
+ String get mapOsmAirportNames => '机场名称';
+
+ @override
+ String get mapOsmPlaceNames => '地名';
+
+ @override
+ String get mapOsmPoi => '地标';
+
+ @override
+ String get mapOsmHouseNumbers => '门牌号码';
+
+ @override
+ String get mapOsmRestoreAll => '全部恢复';
+
+ @override
+ String get mapOsmSectionNatural => '地表与自然';
+
+ @override
+ String get mapOsmSectionRoadsAndBuildings => '道路与建筑';
+
+ @override
+ String get mapOsmSectionLabelsAndPlaces => '地名与标注';
+
@override
String get mapTownLabels => '乡镇名称';
@@ -5767,6 +6042,48 @@ class AppLocalizationsZhHans extends AppLocalizationsZh {
return '「$what」已被拒绝,系统不会再询问。请到设置中开启。';
}
+ @override
+ String get permissionGuideNotification => '请到系统设置中开启通知权限。';
+
+ @override
+ String get permissionGuideForegroundLocation => '请到系统设置中开启精确位置权限。';
+
+ @override
+ String permissionGuideBackgroundLocation(Object option) {
+ return '请在「$option」中改为「允许所有时间」。';
+ }
+
+ @override
+ String get permissionGuideBackgroundExecution =>
+ '请到系统设置中允许后台执行,避免收到通知时被系统暂停。';
+
+ @override
+ String get permissionGuideUnusedPause => '若应用被标记为「未使用」,请在系统设置中改为「允许」。';
+
+ @override
+ String get permissionGuideUnusedFreeSpace => '若应用因缓存空间不足被暂停,请清除缓存后重新打开。';
+
+ @override
+ String get permissionGuideUnusedRevoke => '若应用权限被撤销,请在系统设置中重新授予。';
+
+ @override
+ String get permissionGuideUnusedPlayProtect =>
+ '若被 Play 保护机制暂停,请到 Google Play 中检查应用状态。';
+
+ @override
+ String permissionGuideVendorPower(Object vendor) {
+ return '请到「$vendor」的省电设置中,将本应用设为「不限制」。';
+ }
+
+ @override
+ String get permissionStillRequired => '仍然需要此权限,请到设置中打开。';
+
+ @override
+ String get permissionVerifyManually => '请手动确认此权限已在系统设置中打开。';
+
+ @override
+ String get permissionBackgroundLocationOption => '「允许所有时间」';
+
@override
String get displayTextSize => '文字大小';
@@ -5906,6 +6223,15 @@ class AppLocalizationsZhHans extends AppLocalizationsZh {
@override
String get moreDumpDiagnosticsHint => '上传后复制链接,附在反馈里就不用贴一整页';
+ @override
+ String get dumpIncludeSensitive => '包含精确位置';
+
+ @override
+ String get dumpIncludeSensitiveHint => '包含日志和后台定位中的坐标;未勾选时将以 null 替代';
+
+ @override
+ String get dumpUpload => '上传';
+
@override
String get dumpUploaded => '已上传';
@@ -8002,10 +8328,15 @@ class AppLocalizationsZhHantHk extends AppLocalizationsZh {
String get moreVersionStable => '正式版';
@override
- String get moreVersionNotes => '目前版本';
+ String get moreVersionNotes => '本次更新';
@override
- String get releaseHighlightsTitle => '本次更新';
+ String get moreVersionNotesHighlightsSubtitle => '這個版本做了哪些改變';
+
+ @override
+ String releaseHighlightsTitle(Object train) {
+ return '$train 重點整理';
+ }
@override
String get releaseHighlightsTabNormal => '做了哪些改變';
@@ -8181,6 +8512,113 @@ class AppLocalizationsZhHantHk extends AppLocalizationsZh {
@override
String get onboardingTermsTitle => '服務條款';
+ @override
+ String get mapOsmOverlay => '詳細地圖';
+
+ @override
+ String get mapOsmOverlayHint => '顯示更完整的道路、建物與地名';
+
+ @override
+ String get mapOsmDetails => '詳細設定';
+
+ @override
+ String get moreDataSources => '資料來源';
+
+ @override
+ String get dataSourceTremNet => '探索智慧科技有限公司 — TREM-Net';
+
+ @override
+ String get dataSourceCwa => '交通部中央氣象署 (CWA)';
+
+ @override
+ String get dataSourceJma => '気象庁 (JMA)';
+
+ @override
+ String get dataSourceNcdr => '國家災害防救科技中心 (NCDR)';
+
+ @override
+ String get dataSourceEcmwf =>
+ 'European Centre for Medium-Range Weather Forecasts (ECMWF)';
+
+ @override
+ String get dataSourceNoaaGfs =>
+ 'National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)';
+
+ @override
+ String get dataSourceGovernmentOpenData => '政府資料開放平臺';
+
+ @override
+ String get dataSourceOpenStreetMap => '© OpenStreetMap contributors';
+
+ @override
+ String get dataSourceNasaMoon =>
+ 'National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)';
+
+ @override
+ String mapOsmDetailsHint(int enabled, int total) {
+ return '已啟用 $enabled / 共 $total 個圖層';
+ }
+
+ @override
+ String get mapOsmSurface => '地表';
+
+ @override
+ String get mapOsmParks => '公園';
+
+ @override
+ String get mapOsmLandUse => '土地利用';
+
+ @override
+ String get mapOsmAirportAreas => '機場區域';
+
+ @override
+ String get mapOsmWater => '水域';
+
+ @override
+ String get mapOsmRivers => '河川';
+
+ @override
+ String get mapOsmBoundaries => '邊界';
+
+ @override
+ String get mapOsmBuildings => '建物';
+
+ @override
+ String get mapOsmRoads => '道路';
+
+ @override
+ String get mapOsmRoadNames => '道路名稱';
+
+ @override
+ String get mapOsmWaterNames => '水域名稱';
+
+ @override
+ String get mapOsmPeaks => '山峰';
+
+ @override
+ String get mapOsmAirportNames => '機場名稱';
+
+ @override
+ String get mapOsmPlaceNames => '地名';
+
+ @override
+ String get mapOsmPoi => '地標';
+
+ @override
+ String get mapOsmHouseNumbers => '門牌號碼';
+
+ @override
+ String get mapOsmRestoreAll => '全部恢復';
+
+ @override
+ String get mapOsmSectionNatural => '地表與自然';
+
+ @override
+ String get mapOsmSectionRoadsAndBuildings => '道路與建物';
+
+ @override
+ String get mapOsmSectionLabelsAndPlaces => '地名與標示';
+
@override
String get mapTownLabels => '鄉鎮名稱';
@@ -8727,6 +9165,48 @@ class AppLocalizationsZhHantHk extends AppLocalizationsZh {
return '「$what」已被拒絕,系統不會再詢問。請到設定中開啟。';
}
+ @override
+ String get permissionGuideNotification => '請到系統設定中開啟通知權限。';
+
+ @override
+ String get permissionGuideForegroundLocation => '請到系統設定中開啟精確位置權限。';
+
+ @override
+ String permissionGuideBackgroundLocation(Object option) {
+ return '請在「$option」中改為「允許所有時間」。';
+ }
+
+ @override
+ String get permissionGuideBackgroundExecution =>
+ '請到系統設定中允許背景執行,避免收到通知時被系統暫停。';
+
+ @override
+ String get permissionGuideUnusedPause => '若應用程式被標記為「未使用」,請在系統設定中改為「允許」。';
+
+ @override
+ String get permissionGuideUnusedFreeSpace => '若應用程式因暫存空間不足被暫停,請清除暫存後重新開啟。';
+
+ @override
+ String get permissionGuideUnusedRevoke => '若應用程式權限被撤銷,請在系統設定中重新授予。';
+
+ @override
+ String get permissionGuideUnusedPlayProtect =>
+ '若被 Play 保護機制暫停,請到 Google Play 中檢查應用程式狀態。';
+
+ @override
+ String permissionGuideVendorPower(Object vendor) {
+ return '請到「$vendor」的省電設定中,將本應用程式設為「不限制」。';
+ }
+
+ @override
+ String get permissionStillRequired => '仍然需要此權限,請到設定中開啟。';
+
+ @override
+ String get permissionVerifyManually => '請手動確認此權限已在系統設定中開啟。';
+
+ @override
+ String get permissionBackgroundLocationOption => '「允許所有時間」';
+
@override
String get displayTextSize => '文字大小';
@@ -8866,6 +9346,15 @@ class AppLocalizationsZhHantHk extends AppLocalizationsZh {
@override
String get moreDumpDiagnosticsHint => '上載後複製連結';
+ @override
+ String get dumpIncludeSensitive => '包含精確位置';
+
+ @override
+ String get dumpIncludeSensitiveHint => '包含日誌及背景定位中的座標;未勾選時會以 null 取代';
+
+ @override
+ String get dumpUpload => '上載';
+
@override
String get dumpUploaded => '已上載';
@@ -10962,10 +11451,15 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
String get moreVersionStable => '正式版';
@override
- String get moreVersionNotes => '目前版本';
+ String get moreVersionNotes => '本次更新';
@override
- String get releaseHighlightsTitle => '本次更新';
+ String get moreVersionNotesHighlightsSubtitle => '這個版本做了哪些改變';
+
+ @override
+ String releaseHighlightsTitle(Object train) {
+ return '$train 重點整理';
+ }
@override
String get releaseHighlightsTabNormal => '做了哪些改變';
@@ -11141,6 +11635,113 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
@override
String get onboardingTermsTitle => '服務條款';
+ @override
+ String get mapOsmOverlay => '詳細地圖';
+
+ @override
+ String get mapOsmOverlayHint => '顯示更完整的道路、建物與地名';
+
+ @override
+ String get mapOsmDetails => '詳細設定';
+
+ @override
+ String get moreDataSources => '資料來源';
+
+ @override
+ String get dataSourceTremNet => '探索智慧科技有限公司 — TREM-Net';
+
+ @override
+ String get dataSourceCwa => '交通部中央氣象署 (CWA)';
+
+ @override
+ String get dataSourceJma => '気象庁 (JMA)';
+
+ @override
+ String get dataSourceNcdr => '國家災害防救科技中心 (NCDR)';
+
+ @override
+ String get dataSourceEcmwf =>
+ 'European Centre for Medium-Range Weather Forecasts (ECMWF)';
+
+ @override
+ String get dataSourceNoaaGfs =>
+ 'National Oceanic and Atmospheric Administration / National Centers for Environmental Prediction — Global Forecast System (NOAA/NCEP GFS)';
+
+ @override
+ String get dataSourceGovernmentOpenData => '政府資料開放平臺';
+
+ @override
+ String get dataSourceOpenStreetMap => '© OpenStreetMap contributors';
+
+ @override
+ String get dataSourceNasaMoon =>
+ 'National Aeronautics and Space Administration / Goddard Space Flight Center Scientific Visualization Studio — CGI Moon Kit (NASA/GSFC SVS)';
+
+ @override
+ String mapOsmDetailsHint(int enabled, int total) {
+ return '已啟用 $enabled / 共 $total 個圖層';
+ }
+
+ @override
+ String get mapOsmSurface => '地表';
+
+ @override
+ String get mapOsmParks => '公園';
+
+ @override
+ String get mapOsmLandUse => '土地利用';
+
+ @override
+ String get mapOsmAirportAreas => '機場區域';
+
+ @override
+ String get mapOsmWater => '水域';
+
+ @override
+ String get mapOsmRivers => '河川';
+
+ @override
+ String get mapOsmBoundaries => '邊界';
+
+ @override
+ String get mapOsmBuildings => '建物';
+
+ @override
+ String get mapOsmRoads => '道路';
+
+ @override
+ String get mapOsmRoadNames => '道路名稱';
+
+ @override
+ String get mapOsmWaterNames => '水域名稱';
+
+ @override
+ String get mapOsmPeaks => '山峰';
+
+ @override
+ String get mapOsmAirportNames => '機場名稱';
+
+ @override
+ String get mapOsmPlaceNames => '地名';
+
+ @override
+ String get mapOsmPoi => '地標';
+
+ @override
+ String get mapOsmHouseNumbers => '門牌號碼';
+
+ @override
+ String get mapOsmRestoreAll => '全部恢復';
+
+ @override
+ String get mapOsmSectionNatural => '地表與自然';
+
+ @override
+ String get mapOsmSectionRoadsAndBuildings => '道路與建物';
+
+ @override
+ String get mapOsmSectionLabelsAndPlaces => '地名與標示';
+
@override
String get mapTownLabels => '鄉鎮名稱';
@@ -11687,6 +12288,48 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
return '「$what」已被拒絕,系統不會再詢問。請到設定中開啟。';
}
+ @override
+ String get permissionGuideNotification => '請到系統設定中開啟通知權限。';
+
+ @override
+ String get permissionGuideForegroundLocation => '請到系統設定中開啟精確位置權限。';
+
+ @override
+ String permissionGuideBackgroundLocation(Object option) {
+ return '請在「$option」中改為「允許所有時間」。';
+ }
+
+ @override
+ String get permissionGuideBackgroundExecution =>
+ '請到系統設定中允許背景執行,避免收到通知時被系統暫停。';
+
+ @override
+ String get permissionGuideUnusedPause => '若應用程式被標記為「未使用」,請在系統設定中改為「允許」。';
+
+ @override
+ String get permissionGuideUnusedFreeSpace => '若應用程式因暫存空間不足被暫停,請清除暫存後重新開啟。';
+
+ @override
+ String get permissionGuideUnusedRevoke => '若應用程式權限被撤銷,請在系統設定中重新授予。';
+
+ @override
+ String get permissionGuideUnusedPlayProtect =>
+ '若被 Play 保護機制暫停,請到 Google Play 中檢查應用程式狀態。';
+
+ @override
+ String permissionGuideVendorPower(Object vendor) {
+ return '請到「$vendor」的省電設定中,將本應用程式設為「不限制」。';
+ }
+
+ @override
+ String get permissionStillRequired => '仍然需要此權限,請到設定中開啟。';
+
+ @override
+ String get permissionVerifyManually => '請手動確認此權限已在系統設定中開啟。';
+
+ @override
+ String get permissionBackgroundLocationOption => '「允許所有時間」';
+
@override
String get displayTextSize => '文字大小';
@@ -11826,6 +12469,15 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
@override
String get moreDumpDiagnosticsHint => '上傳後複製連結';
+ @override
+ String get dumpIncludeSensitive => '包含精確位置';
+
+ @override
+ String get dumpIncludeSensitiveHint => '包含日誌與背景定位中的座標;未勾選時會以 null 取代';
+
+ @override
+ String get dumpUpload => '上傳';
+
@override
String get dumpUploaded => '已上傳';
diff --git a/lib/shared/diagnostics/dump_action.dart b/lib/shared/diagnostics/dump_action.dart
index ffa99d323..c876f813c 100644
--- a/lib/shared/diagnostics/dump_action.dart
+++ b/lib/shared/diagnostics/dump_action.dart
@@ -12,6 +12,7 @@ import 'package:dpip/core/platform/background_location.dart';
import 'package:dpip/core/storage/app_database.dart';
import 'package:dpip/l10n/gen/app_localizations.dart';
import 'package:dpip/shared/widgets/dump_link_dialog.dart';
+import 'package:dpip/shared/widgets/dump_upload_dialog.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
@@ -31,6 +32,8 @@ import 'package:talker_flutter/talker_flutter.dart';
Future runDiagnosticsDump(BuildContext context) async {
final l10n = AppLocalizations.of(context);
final messenger = ScaffoldMessenger.of(context);
+ final includeSensitive = await showDumpUploadDialog(context);
+ if (includeSensitive == null || !context.mounted) return false;
final uploader = context.read();
final collector = DiagnosticsCollector(
notifications: context.read(),
@@ -55,14 +58,15 @@ Future runDiagnosticsDump(BuildContext context) async {
message: entry.displayMessage,
),
];
- final url = await uploader.upload(
- buildDump(
- diagnostics: diagnosticsText(
- report.sections,
- redacted: diagnosticsRedactedLabels,
- ),
- logLines: lines,
+ final dump = buildDump(
+ diagnostics: diagnosticsText(
+ report.sections,
+ nulled: includeSensitive ? const {} : diagnosticsSensitiveLabels,
),
+ logLines: lines,
+ );
+ final url = await uploader.upload(
+ includeSensitive ? dump : redactSensitiveDump(dump),
);
if (url == null) {
fail();
diff --git a/lib/shared/map/base_map.dart b/lib/shared/map/base_map.dart
index e6c208ede..b2ca58cf8 100644
--- a/lib/shared/map/base_map.dart
+++ b/lib/shared/map/base_map.dart
@@ -50,6 +50,7 @@ class BaseMap extends StatefulWidget {
this.interactive = true,
this.compassEnabled = true,
this.showUserLocation = true,
+ this.includeTerrainInStyle = true,
this.minZoomPreference = defaultMinZoom,
this.maxZoomPreference = maxZoom,
this.tabIndex,
@@ -142,6 +143,11 @@ class BaseMap extends StatefulWidget {
/// hook for colours.
final bool showUserLocation;
+ /// Whether the initial native style contains the terrain DEM and hillshade.
+ /// Runtime owners can still add terrain later. Omitting it here prevents an
+ /// OSM-first surface from fetching and briefly painting an unused DEM.
+ final bool includeTerrainInStyle;
+
/// Per-surface zoom floor (typhoon may go lower so the whole basin fits).
/// Other layers keep [defaultMinZoom].
final double minZoomPreference;
@@ -438,22 +444,25 @@ class _BaseMapState extends State with WidgetsBindingObserver {
}
/// Style string memoised per palette — all other inputs are const, and
- /// Every [build] used to re-interpolate the full style JSON — the string
- /// only varies by palette and by the town-label directory, so it is memoised
- /// on that pair.
- static final Map<(MapPalette, String), String> _styleCache = {};
-
- static String _styleString(MapPalette palette, String townLabelData) =>
- _styleCache.putIfAbsent(
- (palette, townLabelData),
- () => exptechVectorStyle(
- palette,
- basemapTileUrl: basemapOriginTileUrl,
- glyphsUrl: glyphsOriginUrl,
- terrainTileUrl: terrainOriginTileUrl,
- townLabelData: townLabelData,
- ),
- );
+ /// Every [build] used to re-interpolate the full style JSON — the string only
+ /// varies by palette, town-label directory, and terrain presence, so it is
+ /// memoised on that tuple.
+ static final Map<(MapPalette, String, bool), String> _styleCache = {};
+
+ static String _styleString(
+ MapPalette palette,
+ String townLabelData,
+ bool includeTerrain,
+ ) => _styleCache.putIfAbsent(
+ (palette, townLabelData, includeTerrain),
+ () => exptechVectorStyle(
+ palette,
+ basemapTileUrl: basemapOriginTileUrl,
+ glyphsUrl: glyphsOriginUrl,
+ terrainTileUrl: includeTerrain ? terrainOriginTileUrl : null,
+ townLabelData: townLabelData,
+ ),
+ );
@override
Widget build(BuildContext context) {
@@ -486,6 +495,7 @@ class _BaseMapState extends State with WidgetsBindingObserver {
styleString: _styleString(
palette,
townLabelGeoJson(context.read()),
+ widget.includeTerrainInStyle,
),
// A remount gets a fresh id, so a collided first attempt recovers (see
// [_scheduleReadinessRetry]).
diff --git a/lib/shared/map/map_gsi_overlay.dart b/lib/shared/map/map_gsi_overlay.dart
new file mode 100644
index 000000000..817653363
--- /dev/null
+++ b/lib/shared/map/map_gsi_overlay.dart
@@ -0,0 +1,984 @@
+/// Taiwan street/building detail drawn over the ordinary base map.
+///
+/// The source is a clipped OpenMapTiles dataset built from OpenStreetMap. It is
+/// deliberately a base-map option rather than a [MapLayer]: radar, satellite,
+/// wind, and every other weather product remain active above these streets.
+/// `gsi` remains only in internal IDs to stay compatible with the already
+/// shipped native style and backend route; all user-facing naming is OSM.
+library;
+
+import 'dart:async';
+
+import 'package:dpip/app/theme/app_radius.dart';
+import 'package:dpip/app/theme/app_spacing.dart';
+import 'package:dpip/core/a11y/color_vision.dart';
+import 'package:dpip/core/network/api_paths.dart';
+import 'package:dpip/l10n/gen/app_localizations.dart';
+import 'package:dpip/shared/widgets/map_chip_button.dart';
+import 'package:dpip/shared/widgets/map_menu_toggle_row.dart';
+import 'package:dpip/shared/widgets/section_header.dart';
+import 'package:flutter/material.dart';
+import 'package:maplibre_gl/maplibre_gl.dart';
+
+const String gsiSourceId = 'gsi';
+const String gsiOriginTileUrl =
+ 'https://static.lb.exptech.dev${ApiPaths.mapOsmV1}{z}/{x}/{y}.pbf';
+const double gsiSourceMaxZoom = 14;
+const double gsiDisplayMaxZoom = 18;
+const List gsiBounds = [114.28579, 10.32677, 122.3283, 26.43722];
+
+const VectorSourceProperties gsiSourceProperties = VectorSourceProperties(
+ tiles: [gsiOriginTileUrl],
+ bounds: gsiBounds,
+ minzoom: 0,
+ maxzoom: gsiSourceMaxZoom,
+ attribution: '© OpenStreetMap contributors © OpenMapTiles',
+);
+
+/// User-facing groups from the reference implementation. Some groups own two
+/// MapLibre layers (fill + outline, or road casing + road body), but expose one
+/// switch because either half alone is not meaningful cartography.
+enum GsiLayerGroup {
+ surface,
+ parks,
+ landUse,
+ airportAreas,
+ water,
+ rivers,
+ boundaries,
+ buildings,
+ roads,
+ roadNames,
+ waterNames,
+ peaks,
+ airportNames,
+ placeNames,
+ poi,
+ houseNumbers,
+}
+
+/// Optional details that start hidden. They remain available in the sheet and
+/// [GsiOverlayController.restoreAll] deliberately turns them back on.
+const Set gsiDefaultDisabledGroups = {
+ GsiLayerGroup.parks,
+ GsiLayerGroup.boundaries,
+};
+
+/// Small, scannable groups for the detailed OSM layer sheet. Every native
+/// layer belongs to exactly one user-facing group below, and every group here
+/// belongs to exactly one section.
+enum GsiLayerSection { naturalFeatures, roadsAndBuildings, labelsAndPlaces }
+
+const Map> gsiLayerGroupsBySection = {
+ GsiLayerSection.naturalFeatures: [
+ GsiLayerGroup.surface,
+ GsiLayerGroup.parks,
+ GsiLayerGroup.landUse,
+ GsiLayerGroup.water,
+ GsiLayerGroup.rivers,
+ GsiLayerGroup.peaks,
+ ],
+ GsiLayerSection.roadsAndBuildings: [
+ GsiLayerGroup.roads,
+ GsiLayerGroup.airportAreas,
+ GsiLayerGroup.buildings,
+ GsiLayerGroup.houseNumbers,
+ ],
+ GsiLayerSection.labelsAndPlaces: [
+ GsiLayerGroup.boundaries,
+ GsiLayerGroup.roadNames,
+ GsiLayerGroup.waterNames,
+ GsiLayerGroup.airportNames,
+ GsiLayerGroup.placeNames,
+ GsiLayerGroup.poi,
+ ],
+};
+
+/// State shared by the base-map menu and the native style owner.
+class GsiOverlayController extends ChangeNotifier {
+ GsiOverlayController({
+ this.mutuallyExclusiveTerrain,
+ bool initiallyEnabled = false,
+ }) : _enabled = initiallyEnabled {
+ if (initiallyEnabled) mutuallyExclusiveTerrain?.value = false;
+ }
+
+ final ValueNotifier? mutuallyExclusiveTerrain;
+ bool _enabled;
+ final Set _groups = {...GsiLayerGroup.values}
+ ..removeAll(gsiDefaultDisabledGroups);
+ int _revision = 0;
+
+ bool get enabled => _enabled;
+ int get revision => _revision;
+ int get enabledGroupCount => _groups.length;
+
+ bool groupEnabled(GsiLayerGroup group) => _groups.contains(group);
+
+ void setEnabled(bool value) {
+ // The vector overlay already supplies its own land / road surface. Drawing
+ // hillshade below it both wastes a DEM viewport and muddies that surface,
+ // so selecting OSM turns terrain off in the same synchronous UI update.
+ // The scaffold performs the inverse edge (terrain on -> OSM off).
+ if (value) mutuallyExclusiveTerrain?.value = false;
+ if (_enabled == value) return;
+ _enabled = value;
+ _revision++;
+ notifyListeners();
+ }
+
+ void setGroupEnabled(GsiLayerGroup group, bool value) {
+ final changed = value ? _groups.add(group) : _groups.remove(group);
+ if (!changed) return;
+ _revision++;
+ notifyListeners();
+ }
+
+ void restoreAll() {
+ if (_groups.length == GsiLayerGroup.values.length) return;
+ _groups.addAll(GsiLayerGroup.values);
+ _revision++;
+ notifyListeners();
+ }
+}
+
+/// Makes the one scaffold-owned controller available to every layer menu
+/// without widening [MapLayer.buildTopTrailingChrome] for another base option.
+class GsiOverlayScope extends InheritedNotifier {
+ const GsiOverlayScope({
+ super.key,
+ required GsiOverlayController controller,
+ required super.child,
+ }) : super(notifier: controller);
+
+ static GsiOverlayController? maybeOf(BuildContext context) =>
+ context.dependOnInheritedWidgetOfExactType()?.notifier;
+}
+
+enum GsiLayerKind { fill, line, symbol }
+
+@immutable
+class GsiStyleLayer {
+ const GsiStyleLayer({
+ required this.id,
+ required this.group,
+ required this.kind,
+ required this.sourceLayer,
+ required this.properties,
+ this.minZoom,
+ this.filter,
+ });
+
+ final String id;
+ final GsiLayerGroup group;
+ final GsiLayerKind kind;
+ final String sourceLayer;
+ final LayerProperties properties;
+ final double? minZoom;
+ final dynamic filter;
+
+ LayerProperties propertiesWithVisibility(bool visible) {
+ final visibility = visible ? 'visible' : 'none';
+ return switch (properties) {
+ final FillLayerProperties value => value.copyWith(
+ FillLayerProperties(visibility: visibility),
+ ),
+ final LineLayerProperties value => value.copyWith(
+ LineLayerProperties(visibility: visibility),
+ ),
+ final SymbolLayerProperties value => value.copyWith(
+ SymbolLayerProperties(visibility: visibility),
+ ),
+ _ => throw StateError('Unsupported OSM layer properties for $id'),
+ };
+ }
+}
+
+String _color(String value) => value.vision;
+
+/// The exact source-layer mapping and visual hierarchy from the documented web
+/// implementation, with a light palette added for the app's light theme.
+List gsiStyleLayers(Brightness brightness) {
+ final dark = brightness == Brightness.dark;
+ final halo = _color(dark ? '#212837' : '#F2F3F5');
+ final text = _color(dark ? '#E8ECF2' : '#25282E');
+ return [
+ GsiStyleLayer(
+ id: 'gsi-landcover',
+ group: GsiLayerGroup.surface,
+ kind: GsiLayerKind.fill,
+ sourceLayer: 'landcover',
+ properties: FillLayerProperties(
+ fillColor: [
+ 'match',
+ ['get', 'class'],
+ 'wood',
+ _color(dark ? '#1F3324' : '#CFE3CA'),
+ 'grass',
+ _color(dark ? '#233A26' : '#DBE8C9'),
+ _color(dark ? '#212C22' : '#E5E8DD'),
+ ],
+ fillOpacity: 0.9,
+ ),
+ ),
+ GsiStyleLayer(
+ id: 'gsi-park',
+ group: GsiLayerGroup.parks,
+ kind: GsiLayerKind.fill,
+ sourceLayer: 'park',
+ properties: FillLayerProperties(
+ fillColor: _color(dark ? '#274A2E' : '#CFE8D2'),
+ fillOpacity: 0.55,
+ ),
+ ),
+ GsiStyleLayer(
+ id: 'gsi-park-outline',
+ group: GsiLayerGroup.parks,
+ kind: GsiLayerKind.line,
+ sourceLayer: 'park',
+ properties: LineLayerProperties(
+ lineColor: _color(dark ? '#3F7A4A' : '#79A983'),
+ lineWidth: 1,
+ lineDasharray: const [2, 2],
+ ),
+ ),
+ GsiStyleLayer(
+ id: 'gsi-landuse',
+ group: GsiLayerGroup.landUse,
+ kind: GsiLayerKind.fill,
+ sourceLayer: 'landuse',
+ properties: FillLayerProperties(
+ fillColor: [
+ 'match',
+ ['get', 'class'],
+ 'residential',
+ _color(dark ? '#242830' : '#E3E1DD'),
+ 'commercial',
+ _color(dark ? '#332226' : '#EADADC'),
+ 'industrial',
+ _color(dark ? '#2A2436' : '#DDD8E8'),
+ // Military land remains neutral: red means an alert in DPIP.
+ 'military',
+ _color(dark ? '#2F2B33' : '#D8D4DC'),
+ 'school',
+ _color(dark ? '#332F1F' : '#ECE6CC'),
+ 'university',
+ _color(dark ? '#332F1F' : '#ECE6CC'),
+ 'cemetery',
+ _color(dark ? '#1F2C22' : '#D6E4D7'),
+ _color(dark ? '#242830' : '#E3E1DD'),
+ ],
+ fillOpacity: 0.85,
+ ),
+ ),
+ GsiStyleLayer(
+ id: 'gsi-aeroway-fill',
+ group: GsiLayerGroup.airportAreas,
+ kind: GsiLayerKind.fill,
+ sourceLayer: 'aeroway',
+ filter: const [
+ 'in',
+ ['get', 'class'],
+ [
+ 'literal',
+ ['apron', 'aerodrome', 'heliport'],
+ ],
+ ],
+ properties: FillLayerProperties(
+ fillColor: _color(dark ? '#2E2C3D' : '#DEDCE8'),
+ ),
+ ),
+ GsiStyleLayer(
+ id: 'gsi-aeroway-line',
+ group: GsiLayerGroup.airportAreas,
+ kind: GsiLayerKind.line,
+ sourceLayer: 'aeroway',
+ filter: const [
+ 'in',
+ ['get', 'class'],
+ [
+ 'literal',
+ ['runway', 'taxiway'],
+ ],
+ ],
+ properties: LineLayerProperties(
+ lineColor: _color(dark ? '#5B5578' : '#8F89A7'),
+ lineWidth: const [
+ 'match',
+ ['get', 'class'],
+ 'runway',
+ 8,
+ 3,
+ ],
+ ),
+ ),
+ const GsiStyleLayer(
+ id: 'gsi-water',
+ group: GsiLayerGroup.water,
+ kind: GsiLayerKind.fill,
+ sourceLayer: 'water',
+ // Transparent by design: the ExpTech base map supplies the sea colour,
+ // avoiding a hard rectangle at the OSM dataset bounds.
+ properties: FillLayerProperties(fillColor: 'rgba(0, 0, 0, 0)'),
+ ),
+ GsiStyleLayer(
+ id: 'gsi-waterway',
+ group: GsiLayerGroup.rivers,
+ kind: GsiLayerKind.line,
+ sourceLayer: 'waterway',
+ properties: LineLayerProperties(
+ lineColor: _color(dark ? '#2F6089' : '#5F96C4'),
+ lineWidth: const [
+ 'match',
+ ['get', 'class'],
+ 'river',
+ 2.5,
+ 'stream',
+ 1.2,
+ 1,
+ ],
+ ),
+ ),
+ GsiStyleLayer(
+ id: 'gsi-boundary',
+ group: GsiLayerGroup.boundaries,
+ kind: GsiLayerKind.line,
+ sourceLayer: 'boundary',
+ properties: LineLayerProperties(
+ lineColor: [
+ 'step',
+ ['get', 'admin_level'],
+ _color(dark ? '#C77BC0' : '#8E4E8B'),
+ 3,
+ _color(dark ? '#B579AE' : '#885C84'),
+ 5,
+ _color(dark ? '#8A6A8B' : '#776174'),
+ 8,
+ _color(dark ? '#5F5063' : '#6C626D'),
+ ],
+ lineWidth: const [
+ 'step',
+ ['get', 'admin_level'],
+ 2.4,
+ 5,
+ 1.4,
+ 8,
+ 0.8,
+ ],
+ lineDasharray: const [3, 2],
+ ),
+ ),
+ GsiStyleLayer(
+ id: 'gsi-building',
+ group: GsiLayerGroup.buildings,
+ kind: GsiLayerKind.fill,
+ sourceLayer: 'building',
+ minZoom: 13,
+ properties: FillLayerProperties(
+ fillColor: _color(dark ? '#3A3A3F' : '#D3D0CC'),
+ fillOutlineColor: _color(dark ? '#55555C' : '#AAA59F'),
+ ),
+ ),
+ GsiStyleLayer(
+ id: 'gsi-transportation-case',
+ group: GsiLayerGroup.roads,
+ kind: GsiLayerKind.line,
+ sourceLayer: 'transportation',
+ filter: const [
+ '!=',
+ ['get', 'class'],
+ 'ferry',
+ ],
+ properties: LineLayerProperties(
+ lineColor: _color(dark ? '#0C0E14' : '#FFFFFF'),
+ lineCap: 'round',
+ lineJoin: 'round',
+ lineWidth: const [
+ 'interpolate',
+ ['linear'],
+ ['zoom'],
+ 8,
+ [
+ 'match',
+ ['get', 'class'],
+ 'motorway',
+ 1.2,
+ 'trunk',
+ 1,
+ 'primary',
+ 0.8,
+ 0.4,
+ ],
+ 16,
+ [
+ 'match',
+ ['get', 'class'],
+ 'motorway',
+ 14,
+ 'trunk',
+ 11,
+ 'primary',
+ 9,
+ [
+ 'match',
+ ['get', 'class'],
+ 'service',
+ 3,
+ 'path',
+ 2,
+ 6,
+ ],
+ ],
+ ],
+ ),
+ ),
+ GsiStyleLayer(
+ id: 'gsi-transportation',
+ group: GsiLayerGroup.roads,
+ kind: GsiLayerKind.line,
+ sourceLayer: 'transportation',
+ filter: const [
+ '!=',
+ ['get', 'class'],
+ 'ferry',
+ ],
+ properties: LineLayerProperties(
+ lineCap: 'round',
+ lineJoin: 'round',
+ lineColor: [
+ 'match',
+ ['get', 'class'],
+ 'motorway',
+ _color(dark ? '#E8A33D' : '#D4851F'),
+ 'trunk',
+ _color(dark ? '#D99A4E' : '#C7822D'),
+ 'primary',
+ _color(dark ? '#C99A5F' : '#B88942'),
+ 'secondary',
+ _color(dark ? '#8F7A4F' : '#9A8157'),
+ 'rail',
+ _color(dark ? '#7A7A82' : '#77777D'),
+ 'service',
+ _color(dark ? '#3D3D44' : '#C7C4BE'),
+ 'path',
+ _color(dark ? '#5F5540' : '#A89467'),
+ _color(dark ? '#4A4A52' : '#B7B3AD'),
+ ],
+ lineWidth: const [
+ 'interpolate',
+ ['linear'],
+ ['zoom'],
+ 8,
+ [
+ 'match',
+ ['get', 'class'],
+ 'motorway',
+ 1,
+ 'trunk',
+ 0.8,
+ 'primary',
+ 0.6,
+ 0.3,
+ ],
+ 16,
+ [
+ 'match',
+ ['get', 'class'],
+ 'motorway',
+ 11,
+ 'trunk',
+ 8,
+ 'primary',
+ 6.5,
+ [
+ 'match',
+ ['get', 'class'],
+ 'service',
+ 1.5,
+ 'path',
+ 1,
+ 4,
+ ],
+ ],
+ ],
+ // MapLibre Native on iOS accepts a constant dash pattern but aborts
+ // inside MLNLineStyleLayer when this property is data-driven. Keep the
+ // shared road layer solid; a native Objective-C exception cannot be
+ // recovered by Dart's try/catch.
+ ),
+ ),
+ GsiStyleLayer(
+ id: 'gsi-transportation-name',
+ group: GsiLayerGroup.roadNames,
+ kind: GsiLayerKind.symbol,
+ sourceLayer: 'transportation_name',
+ minZoom: 13,
+ properties: SymbolLayerProperties(
+ symbolPlacement: 'line',
+ textField: _nameExpression,
+ textFont: const ['Noto Sans TC Regular'],
+ textSize: 11,
+ textColor: _color(dark ? '#D9B877' : '#725B25'),
+ textHaloColor: halo,
+ textHaloWidth: 1.2,
+ ),
+ ),
+ GsiStyleLayer(
+ id: 'gsi-water-name',
+ group: GsiLayerGroup.waterNames,
+ kind: GsiLayerKind.symbol,
+ sourceLayer: 'water_name',
+ properties: SymbolLayerProperties(
+ textField: _nameExpression,
+ textFont: const ['Noto Sans TC Regular'],
+ textSize: 12,
+ textLetterSpacing: 0.05,
+ textColor: _color(dark ? '#7CB3DE' : '#326D9A'),
+ textHaloColor: halo,
+ textHaloWidth: 1.2,
+ ),
+ ),
+ GsiStyleLayer(
+ id: 'gsi-mountain-peak',
+ group: GsiLayerGroup.peaks,
+ kind: GsiLayerKind.symbol,
+ sourceLayer: 'mountain_peak',
+ properties: SymbolLayerProperties(
+ textField: const [
+ 'format',
+ _nameExpression,
+ {},
+ '\n',
+ {},
+ [
+ 'concat',
+ [
+ 'to-string',
+ ['get', 'ele'],
+ ],
+ 'm',
+ ],
+ {'font-scale': 0.85},
+ ],
+ textFont: const ['Noto Sans TC Regular'],
+ textSize: 12,
+ textAnchor: 'top',
+ textOffset: const [0, 0.4],
+ textJustify: 'center',
+ textColor: _color(dark ? '#D99A6C' : '#875332'),
+ textHaloColor: halo,
+ textHaloWidth: 1.4,
+ ),
+ ),
+ GsiStyleLayer(
+ id: 'gsi-aerodrome-label',
+ group: GsiLayerGroup.airportNames,
+ kind: GsiLayerKind.symbol,
+ sourceLayer: 'aerodrome_label',
+ properties: SymbolLayerProperties(
+ textField: _nameExpression,
+ textFont: const ['Noto Sans TC Regular'],
+ textSize: 13,
+ textColor: _color(dark ? '#A89ADB' : '#66539C'),
+ textHaloColor: halo,
+ textHaloWidth: 1.4,
+ ),
+ ),
+ GsiStyleLayer(
+ id: 'gsi-place',
+ group: GsiLayerGroup.placeNames,
+ kind: GsiLayerKind.symbol,
+ sourceLayer: 'place',
+ properties: SymbolLayerProperties(
+ textField: _nameExpression,
+ textFont: const ['Noto Sans TC Regular'],
+ textSize: const [
+ 'match',
+ ['get', 'class'],
+ 'country',
+ 18,
+ 'city',
+ 15,
+ 'town',
+ 13,
+ 'village',
+ 11,
+ 10,
+ ],
+ textColor: text,
+ textHaloColor: halo,
+ textHaloWidth: 1.4,
+ ),
+ ),
+ GsiStyleLayer(
+ id: 'gsi-poi',
+ group: GsiLayerGroup.poi,
+ kind: GsiLayerKind.symbol,
+ sourceLayer: 'poi',
+ minZoom: 14,
+ properties: SymbolLayerProperties(
+ textField: _nameExpression,
+ textFont: const ['Noto Sans TC Regular'],
+ textSize: 10,
+ textOffset: const [0, 0.6],
+ textAnchor: 'top',
+ textColor: _color(dark ? '#A9B4C2' : '#555D68'),
+ textHaloColor: halo,
+ textHaloWidth: 1,
+ ),
+ ),
+ GsiStyleLayer(
+ id: 'gsi-housenumber',
+ group: GsiLayerGroup.houseNumbers,
+ kind: GsiLayerKind.symbol,
+ sourceLayer: 'housenumber',
+ minZoom: 16,
+ properties: SymbolLayerProperties(
+ textField: const ['get', 'housenumber'],
+ textFont: const ['Noto Sans TC Regular'],
+ textSize: 9,
+ textColor: _color(dark ? '#9A958A' : '#6F6A5F'),
+ ),
+ ),
+ ];
+}
+
+const List