mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-13 15:51:00 +00:00
2e1dca9fe9
Settings, Integrations, wanderer gains an optional background check of the trails you imported, off until you switch it on. While on, TREK reads the short record of each such trail at most once a day (never its GPX file) and leaves a hint when the trail may have moved on: "may have changed" when only wanderer's change time moved, "changed" when its name or description proves it, and "not checkable" when the trail is gone, no longer yours or carries no change time. Nothing is ever said to be unchanged. A new hint arrives as a notification that opens the tour (a new ?place= link in the planner); the tour's provenance shows it with the source check right beside it, and the card lists all open hints in a dialog, each leading to its tour. The check reads the source in full as before and spends the hint; taking a change in stays the confirmed reimport. No tour is ever changed or deleted. The check only asks through your own connection, only about trails your account imported into trips you can still open, and stops when you switch it off, remove the connection, wanderer refuses the token (until a test passes or a new token is saved) or the admin switches wanderer off; hints and snapshots stay. A run asks at most 25 connections for at most 10 records each, one after another, and an instance that fails (an outage, a rate limit) is left alone for an hour, doubling up to two days. Server: migration 046120 adds the switch and the run bookkeeping to wanderer_connections and the tour_source_hints table (one row per snapshot, for its importer, gone with it). WandererWatchService and an hourly wanderer-watch job on the CronRegistrar live in the tours domain and read through WandererService; GET and PUT /api/integrations/wanderer/watch and GET /api/trips/:tripId/tours/wanderer/sources/:placeId/hint (place_edit, like the check) answer with @trek/shared contracts. A new user notification event, wanderer_source_hint, can be muted per channel. Saving a new token now clears what the last check said about the old one. There is no MCP tool, as for the rest of the personal wanderer connection. All 27 locales carry the strings, and the admin wiki page says what the check does.
115 lines
5.8 KiB
TypeScript
115 lines
5.8 KiB
TypeScript
import type { NotificationLocale } from '../externalNotifications/types';
|
|
import { pluralForm } from '../plural';
|
|
|
|
const ar: NotificationLocale = {
|
|
email: {
|
|
footer: 'تلقيت هذا لأنك قمت بتفعيل الإشعارات في TREK.',
|
|
manage: 'إدارة التفضيلات',
|
|
madeWith: 'Made with',
|
|
openTrek: 'فتح TREK',
|
|
},
|
|
events: {
|
|
trip_invite: (p) => ({
|
|
title: `دعوة إلى "${p.trip}"`,
|
|
body: `${p.actor} دعا ${p.invitee || 'عضو'} إلى الرحلة "${p.trip}".`,
|
|
}),
|
|
booking_change: (p) => ({
|
|
title: `حجز جديد: ${p.booking}`,
|
|
body: `${p.actor} أضاف حجز "${p.booking}" (${p.type}) إلى "${p.trip}".`,
|
|
}),
|
|
trip_reminder: (p) => ({
|
|
title: `تذكير: ${p.trip}`,
|
|
body: `رحلتك "${p.trip}" تقترب!`,
|
|
}),
|
|
todo_due: (p) => ({
|
|
title: `مهمة مستحقة: ${p.todo}`,
|
|
body: `"${p.todo}" في "${p.trip}" مستحقة في ${p.due}.`,
|
|
}),
|
|
vacay_invite: (p) => ({
|
|
title: 'دعوة دمج الإجازة',
|
|
body: `${p.actor} يدعوك لدمج خطط الإجازة. افتح TREK للقبول أو الرفض.`,
|
|
}),
|
|
vacay_share: (p) => ({
|
|
title: 'تمت مشاركة تقويم Vacay',
|
|
body: `${p.actor} شارك تقويم إجازاته معك. افتح TREK لعرضه.`,
|
|
}),
|
|
collection_invite: (p) => ({
|
|
title: 'دعوة إلى مجموعة',
|
|
body: `${p.actor} يدعوك لمشاركة مجموعة. افتح TREK للقبول أو الرفض.`,
|
|
}),
|
|
photos_shared: (p) => ({
|
|
title: pluralForm(p.count, 'ar', {
|
|
zero: 'لم تتم مشاركة أي صورة',
|
|
one: 'تمت مشاركة صورة واحدة',
|
|
two: 'تمت مشاركة صورتين',
|
|
few: `تمت مشاركة ${p.count} صور`,
|
|
many: `تمت مشاركة ${p.count} صورة`,
|
|
other: `تمت مشاركة ${p.count} صورة`,
|
|
}),
|
|
body: pluralForm(p.count, 'ar', {
|
|
zero: `${p.actor} لم يشارك أي صورة في "${p.trip}".`,
|
|
one: `${p.actor} شارك صورة واحدة في "${p.trip}".`,
|
|
two: `${p.actor} شارك صورتين في "${p.trip}".`,
|
|
few: `${p.actor} شارك ${p.count} صور في "${p.trip}".`,
|
|
many: `${p.actor} شارك ${p.count} صورة في "${p.trip}".`,
|
|
other: `${p.actor} شارك ${p.count} صورة في "${p.trip}".`,
|
|
}),
|
|
}),
|
|
collab_message: (p) => ({
|
|
title: `رسالة جديدة في "${p.trip}"`,
|
|
body: `${p.actor}: ${p.preview}`,
|
|
}),
|
|
packing_tagged: (p) => ({
|
|
title: `قائمة التعبئة: ${p.category}`,
|
|
body: `${p.actor} عيّنك في فئة "${p.category}" في "${p.trip}".`,
|
|
}),
|
|
version_available: (p) => ({
|
|
title: 'إصدار TREK جديد متاح',
|
|
body: `TREK ${p.version} متاح الآن. تفضل بزيارة لوحة الإدارة للتحديث.`,
|
|
}),
|
|
replica_failure: (p) => ({
|
|
title: 'فشل النسخة المتماثلة للتخزين',
|
|
body:
|
|
`فشلت الكتابة على النسخة المتماثلة '${p.backend}': ${p.op} لـ ${p.key} — ${p.error}.` +
|
|
(p.suppressed !== '0'
|
|
? pluralForm(p.suppressed, 'ar', {
|
|
zero: ' لم يتم تجاهل أي حالة فشل إضافية منذ آخر إشعار.',
|
|
one: ' تم تجاهل حالة فشل إضافية واحدة منذ آخر إشعار.',
|
|
two: ' تم تجاهل حالتَي فشل إضافيتين منذ آخر إشعار.',
|
|
few: ` تم تجاهل ${p.suppressed} حالات فشل إضافية منذ آخر إشعار.`,
|
|
many: ` تم تجاهل ${p.suppressed} حالة فشل إضافية منذ آخر إشعار.`,
|
|
other: ` تم تجاهل ${p.suppressed} حالة فشل إضافية منذ آخر إشعار.`,
|
|
})
|
|
: ''),
|
|
}),
|
|
paddle_region_requested: (p) => ({
|
|
title: 'طلب منطقة تجديف',
|
|
body: `${p.actor} يخطط لرحلة تجديف في ${p.region}. حمّل بياناتها المائية أو ارفضها في لوحة الإدارة ضمن الإضافات.`,
|
|
}),
|
|
synology_session_cleared: () => ({
|
|
title: 'تمت إعادة تعيين جلسة Synology',
|
|
body: 'تغيّر حسابك أو رابط Synology. تم تسجيل خروجك من Synology Photos.',
|
|
}),
|
|
wanderer_source_hint: (p) => ({
|
|
title: `درب wanderer: ${p.tour}`,
|
|
body:
|
|
p.state === 'changed'
|
|
? `تغيّر «${p.tour}» في «${p.trip}» على wanderer. افتح الجولة وتحقق من مصدرها لترى كل التغييرات. لا يتغير شيء في الرحلة من تلقاء نفسه.`
|
|
: p.state === 'unverifiable'
|
|
? `لم يعد بالإمكان التحقق من «${p.tour}» في «${p.trip}» على wanderer. تبقى الجولة في رحلتك كما هي.`
|
|
: `ربما تغيّر «${p.tour}» في «${p.trip}» على wanderer. افتح الجولة وتحقق من مصدرها. لا يتغير شيء في الرحلة من تلقاء نفسه.`,
|
|
}),
|
|
plugin_notification: (p) => ({ title: p.title ?? '', body: p.body ?? '' }),
|
|
},
|
|
passwordReset: {
|
|
subject: 'إعادة تعيين كلمة المرور',
|
|
greeting: 'مرحبا',
|
|
body: 'تلقينا طلبًا لإعادة تعيين كلمة المرور لحسابك في TREK. انقر على الزر أدناه لتعيين كلمة مرور جديدة.',
|
|
ctaIntro: 'إعادة تعيين كلمة المرور',
|
|
expiry: 'تنتهي صلاحية هذا الرابط خلال 60 دقيقة.',
|
|
ignore: 'إذا لم تطلب هذا، يمكنك تجاهل هذه الرسالة — لن تتغير كلمة المرور الخاصة بك.',
|
|
},
|
|
};
|
|
|
|
export default ar;
|