Files
TREK/shared/src/i18n/ko/externalNotifications.ts
T
Maurice 2e1dca9fe9 feat(tours): let a background check hint at changes of your own wanderer trails
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.
2026-10-20 15:35:32 +02:00

91 lines
4.3 KiB
TypeScript

import type { NotificationLocale } from '../externalNotifications/types';
const ko: 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.trip}"에 "${p.booking}" (${p.type}) 예약을 추가했습니다.`,
}),
trip_reminder: (p) => ({
title: `여행 알림: ${p.trip}`,
body: `"${p.trip}" 여행이 곧 시작됩니다!`,
}),
todo_due: (p) => ({
title: `할 일 마감: ${p.todo}`,
body: `"${p.trip}"의 "${p.todo}"은(는) ${p.due}에 마감됩니다.`,
}),
vacay_invite: (p) => ({
title: 'Vacay Fusion 초대',
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: `사진 ${p.count}장이 공유되었습니다`,
body: `${p.actor}이(가) "${p.trip}"에서 사진 ${p.count}장을 공유했습니다.`,
}),
collab_message: (p) => ({
title: `"${p.trip}"의 새 메시지`,
body: `${p.actor}: ${p.preview}`,
}),
packing_tagged: (p) => ({
title: `짐 꾸리기: ${p.category}`,
body: `${p.actor}이(가) "${p.trip}"의 "${p.category}" 카테고리에 당신을 할당했습니다.`,
}),
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' ? ` 마지막 알림 이후 실패가 ${p.suppressed}건 더 있었지만 따로 알리지 않았습니다.` : ''),
}),
paddle_region_requested: (p) => ({
title: '패들 지역 요청',
body: `${p.actor}님이 ${p.region}에서 패들 투어를 계획하고 있습니다. 관리 화면의 애드온에서 수역 데이터를 불러오거나 거절하세요.`,
}),
synology_session_cleared: () => ({
title: 'Synology 세션이 초기화되었습니다',
body: 'Synology 계정 또는 URL이 변경되었습니다. Synology Photos에서 로그아웃되었습니다.',
}),
wanderer_source_hint: (p) => ({
title: `wanderer 트레일: ${p.tour}`,
body:
p.state === 'changed'
? `"${p.trip}"의 "${p.tour}"이(가) wanderer에서 변경되었습니다. 투어를 열고 소스를 확인하면 모든 변경을 볼 수 있습니다. 여행의 내용은 저절로 바뀌지 않습니다.`
: p.state === 'unverifiable'
? `"${p.trip}"의 "${p.tour}"은(는) 더 이상 wanderer에서 확인할 수 없습니다. 여행의 투어는 그대로 유지됩니다.`
: `"${p.trip}"의 "${p.tour}"이(가) wanderer에서 바뀌었을 수 있습니다. 투어를 열고 소스를 확인하세요. 여행의 내용은 저절로 바뀌지 않습니다.`,
}),
plugin_notification: (p) => ({ title: p.title ?? '', body: p.body ?? '' }),
},
passwordReset: {
subject: '비밀번호 재설정',
greeting: '안녕하세요',
body: 'TREK 계정 비밀번호 재설정 요청을 받았습니다. 아래 버튼을 클릭하여 새 비밀번호를 설정하세요.',
ctaIntro: '비밀번호 재설정',
expiry: '이 링크는 60분 후에 만료됩니다.',
ignore: '본인이 요청하지 않으셨다면 이 이메일을 무시하셔도 됩니다 — 비밀번호는 변경되지 않습니다.',
},
};
export default ko;