Merge remote-tracking branch 'refs/remotes/pull/495' into feat/naver-support

This commit is contained in:
jubnl
2026-04-15 04:38:50 +02:00
22 changed files with 438 additions and 38 deletions
+2
View File
@@ -196,6 +196,8 @@ export const placesApi = {
},
importGoogleList: (tripId: number | string, url: string) =>
apiClient.post(`/trips/${tripId}/places/import/google-list`, { url }).then(r => r.data),
importNaverList: (tripId: number | string, url: string) =>
apiClient.post(`/trips/${tripId}/places/import/naver-list`, { url }).then(r => r.data),
}
export const assignmentsApi = {
+64 -31
View File
@@ -1,6 +1,6 @@
import React from 'react'
import ReactDOM from 'react-dom'
import { useState, useRef, useMemo, useCallback } from 'react'
import { useState, useRef, useMemo, useCallback, useEffect } from 'react'
import DOM from 'react-dom'
import { Search, Plus, X, CalendarDays, Pencil, Trash2, ExternalLink, Navigation, Upload, ChevronDown, Check, MapPin, Eye } from 'lucide-react'
import PlaceAvatar from '../shared/PlaceAvatar'
@@ -12,6 +12,7 @@ import { useContextMenu, ContextMenu } from '../shared/ContextMenu'
import { placesApi } from '../../api/client'
import { useTripStore } from '../../store/tripStore'
import { useCanDo } from '../../store/permissionsStore'
import { useAddonStore } from '../../store/addonStore'
import type { Place, Category, Day, AssignmentsMap } from '../../types'
interface PlacesSidebarProps {
@@ -45,6 +46,7 @@ const PlacesSidebar = React.memo(function PlacesSidebar({
const loadTrip = useTripStore((s) => s.loadTrip)
const can = useCanDo()
const canEditPlaces = can('place_edit', trip)
const isNaverListImportEnabled = useAddonStore((s) => s.isEnabled('naver_list_import'))
const handleGpxImport = async (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0]
@@ -68,22 +70,34 @@ const PlacesSidebar = React.memo(function PlacesSidebar({
}
}
const [googleListOpen, setGoogleListOpen] = useState(false)
const [googleListUrl, setGoogleListUrl] = useState('')
const [googleListLoading, setGoogleListLoading] = useState(false)
const [listImportOpen, setListImportOpen] = useState(false)
const [listImportUrl, setListImportUrl] = useState('')
const [listImportLoading, setListImportLoading] = useState(false)
const [listImportProvider, setListImportProvider] = useState<'google' | 'naver'>('google')
const availableListImportProviders: Array<'google' | 'naver'> = isNaverListImportEnabled ? ['google', 'naver'] : ['google']
const hasMultipleListImportProviders = availableListImportProviders.length > 1
const handleGoogleListImport = async () => {
if (!googleListUrl.trim()) return
setGoogleListLoading(true)
useEffect(() => {
if (!isNaverListImportEnabled && listImportProvider === 'naver') {
setListImportProvider('google')
}
}, [isNaverListImportEnabled, listImportProvider])
const handleListImport = async () => {
if (!listImportUrl.trim()) return
setListImportLoading(true)
try {
const result = await placesApi.importGoogleList(tripId, googleListUrl.trim())
const provider = listImportProvider === 'naver' && isNaverListImportEnabled ? 'naver' : 'google'
const result = provider === 'google'
? await placesApi.importGoogleList(tripId, listImportUrl.trim())
: await placesApi.importNaverList(tripId, listImportUrl.trim())
await loadTrip(tripId)
toast.success(t('places.googleListImported', { count: result.count, list: result.listName }))
setGoogleListOpen(false)
setGoogleListUrl('')
toast.success(t(provider === 'google' ? 'places.googleListImported' : 'places.naverListImported', { count: result.count, list: result.listName }))
setListImportOpen(false)
setListImportUrl('')
if (result.places?.length > 0) {
const importedIds: number[] = result.places.map((p: { id: number }) => p.id)
pushUndo?.(t('undo.importGoogleList'), async () => {
pushUndo?.(t(provider === 'google' ? 'undo.importGoogleList' : 'undo.importNaverList'), async () => {
for (const id of importedIds) {
try { await placesApi.delete(tripId, id) } catch {}
}
@@ -91,9 +105,10 @@ const PlacesSidebar = React.memo(function PlacesSidebar({
})
}
} catch (err: any) {
toast.error(err?.response?.data?.error || t('places.googleListError'))
const provider = listImportProvider === 'naver' && isNaverListImportEnabled ? 'naver' : 'google'
toast.error(err?.response?.data?.error || t(provider === 'google' ? 'places.googleListError' : 'places.naverListError'))
} finally {
setGoogleListLoading(false)
setListImportLoading(false)
}
}
@@ -160,7 +175,7 @@ const PlacesSidebar = React.memo(function PlacesSidebar({
<Upload size={11} strokeWidth={2} /> {t('places.importGpx')}
</button>
<button
onClick={() => setGoogleListOpen(true)}
onClick={() => setListImportOpen(true)}
style={{
display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 5,
flex: 1, padding: '5px 12px', borderRadius: 8,
@@ -169,7 +184,7 @@ const PlacesSidebar = React.memo(function PlacesSidebar({
cursor: 'pointer', fontFamily: 'inherit',
}}
>
<MapPin size={11} strokeWidth={2} /> {t('places.importGoogleList')}
<MapPin size={11} strokeWidth={2} /> {t(hasMultipleListImportProviders ? 'places.importList' : 'places.importGoogleList')}
</button>
</div>
</>}
@@ -447,9 +462,9 @@ const PlacesSidebar = React.memo(function PlacesSidebar({
</div>,
document.body
)}
{googleListOpen && ReactDOM.createPortal(
{listImportOpen && ReactDOM.createPortal(
<div
onClick={() => { setGoogleListOpen(false); setGoogleListUrl('') }}
onClick={() => { setListImportOpen(false); setListImportUrl('') }}
style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.4)', zIndex: 99999, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16 }}
>
<div
@@ -457,17 +472,35 @@ const PlacesSidebar = React.memo(function PlacesSidebar({
style={{ background: 'var(--bg-card)', borderRadius: 16, width: '100%', maxWidth: 440, padding: 24, boxShadow: '0 8px 32px rgba(0,0,0,0.2)' }}
>
<div style={{ fontSize: 15, fontWeight: 700, color: 'var(--text-primary)', marginBottom: 4 }}>
{t('places.importGoogleList')}
{t('places.importList')}
</div>
{hasMultipleListImportProviders && (
<div style={{ display: 'flex', gap: 6, marginBottom: 10 }}>
{availableListImportProviders.map(provider => (
<button
key={provider}
onClick={() => setListImportProvider(provider)}
style={{
padding: '6px 10px', borderRadius: 20, border: 'none', cursor: 'pointer',
fontSize: 11, fontWeight: 600, fontFamily: 'inherit',
background: listImportProvider === provider ? 'var(--accent)' : 'var(--bg-tertiary)',
color: listImportProvider === provider ? 'var(--accent-text)' : 'var(--text-muted)',
}}
>
{provider === 'google' ? t('places.importGoogleList') : t('places.importNaverList')}
</button>
))}
</div>
)}
<div style={{ fontSize: 12, color: 'var(--text-faint)', marginBottom: 16 }}>
{t('places.googleListHint')}
{t(listImportProvider === 'google' ? 'places.googleListHint' : 'places.naverListHint')}
</div>
<input
type="text"
value={googleListUrl}
onChange={e => setGoogleListUrl(e.target.value)}
onKeyDown={e => { if (e.key === 'Enter' && !googleListLoading) handleGoogleListImport() }}
placeholder="https://maps.app.goo.gl/..."
value={listImportUrl}
onChange={e => setListImportUrl(e.target.value)}
onKeyDown={e => { if (e.key === 'Enter' && !listImportLoading) handleListImport() }}
placeholder={listImportProvider === 'google' ? 'https://maps.app.goo.gl/...' : 'https://naver.me/...'}
autoFocus
style={{
width: '100%', padding: '10px 14px', borderRadius: 10,
@@ -478,7 +511,7 @@ const PlacesSidebar = React.memo(function PlacesSidebar({
/>
<div style={{ display: 'flex', gap: 8, marginTop: 16, justifyContent: 'flex-end' }}>
<button
onClick={() => { setGoogleListOpen(false); setGoogleListUrl('') }}
onClick={() => { setListImportOpen(false); setListImportUrl('') }}
style={{
padding: '8px 16px', borderRadius: 10, border: '1px solid var(--border-primary)',
background: 'none', color: 'var(--text-primary)', fontSize: 13, fontWeight: 500,
@@ -488,17 +521,17 @@ const PlacesSidebar = React.memo(function PlacesSidebar({
{t('common.cancel')}
</button>
<button
onClick={handleGoogleListImport}
disabled={!googleListUrl.trim() || googleListLoading}
onClick={handleListImport}
disabled={!listImportUrl.trim() || listImportLoading}
style={{
padding: '8px 16px', borderRadius: 10, border: 'none',
background: !googleListUrl.trim() || googleListLoading ? 'var(--bg-tertiary)' : 'var(--accent)',
color: !googleListUrl.trim() || googleListLoading ? 'var(--text-faint)' : 'var(--accent-text)',
fontSize: 13, fontWeight: 500, cursor: !googleListUrl.trim() || googleListLoading ? 'default' : 'pointer',
background: !listImportUrl.trim() || listImportLoading ? 'var(--bg-tertiary)' : 'var(--accent)',
color: !listImportUrl.trim() || listImportLoading ? 'var(--text-faint)' : 'var(--accent-text)',
fontSize: 13, fontWeight: 500, cursor: !listImportUrl.trim() || listImportLoading ? 'default' : 'pointer',
fontFamily: 'inherit',
}}
>
{googleListLoading ? t('common.loading') : t('common.import')}
{listImportLoading ? t('common.loading') : t('common.import')}
</button>
</div>
</div>
+6
View File
@@ -895,10 +895,15 @@ const ar: Record<string, string | { name: string; category: string }[]> = {
'places.importGpx': 'GPX',
'places.gpxImported': 'تم استيراد {count} مكان من GPX',
'places.gpxError': 'فشل استيراد GPX',
'places.importList': 'استيراد قائمة',
'places.importGoogleList': 'قائمة Google',
'places.importNaverList': 'قائمة Naver',
'places.googleListHint': 'الصق رابط قائمة Google Maps المشتركة لاستيراد جميع الأماكن.',
'places.googleListImported': 'تم استيراد {count} أماكن من "{list}"',
'places.googleListError': 'فشل استيراد قائمة Google Maps',
'places.naverListHint': 'الصق رابط قائمة Naver Maps مشتركة لاستيراد جميع الأماكن.',
'places.naverListImported': 'تم استيراد {count} مكان من "{list}"',
'places.naverListError': 'فشل استيراد قائمة Naver Maps',
'places.viewDetails': 'عرض التفاصيل',
'places.urlResolved': 'تم استيراد المكان من الرابط',
'places.assignToDay': 'إلى أي يوم تريد الإضافة؟',
@@ -1713,6 +1718,7 @@ const ar: Record<string, string | { name: string; category: string }[]> = {
'undo.lock': 'تم تبديل قفل المكان',
'undo.importGpx': 'استيراد GPX',
'undo.importGoogleList': 'استيراد خرائط Google',
'undo.importNaverList': 'استيراد خرائط Naver',
// Notifications
'notifications.title': 'الإشعارات',
+6
View File
@@ -865,10 +865,15 @@ const br: Record<string, string | { name: string; category: string }[]> = {
'places.importGpx': 'GPX',
'places.gpxImported': '{count} lugares importados do GPX',
'places.gpxError': 'Falha ao importar GPX',
'places.importList': 'Importar lista',
'places.importGoogleList': 'Lista Google',
'places.importNaverList': 'Lista Naver',
'places.googleListHint': 'Cole um link compartilhado de uma lista do Google Maps para importar todos os lugares.',
'places.googleListImported': '{count} lugares importados de "{list}"',
'places.googleListError': 'Falha ao importar lista do Google Maps',
'places.naverListHint': 'Cole um link compartilhado de uma lista do Naver Maps para importar todos os lugares.',
'places.naverListImported': '{count} lugares importados de "{list}"',
'places.naverListError': 'Falha ao importar lista do Naver Maps',
'places.viewDetails': 'Ver detalhes',
'places.urlResolved': 'Lugar importado da URL',
'places.assignToDay': 'Adicionar a qual dia?',
@@ -1662,6 +1667,7 @@ const br: Record<string, string | { name: string; category: string }[]> = {
'undo.lock': 'Bloqueio do local alternado',
'undo.importGpx': 'Importação de GPX',
'undo.importGoogleList': 'Importação do Google Maps',
'undo.importNaverList': 'Importação do Naver Maps',
// Notifications
'notifications.title': 'Notificações',
+6
View File
@@ -894,10 +894,15 @@ const cs: Record<string, string | { name: string; category: string }[]> = {
'places.gpxImported': '{count} míst importováno z GPX',
'places.urlResolved': 'Místo importováno z URL',
'places.gpxError': 'Import GPX se nezdařil',
'places.importList': 'Import seznamu',
'places.importGoogleList': 'Google Seznam',
'places.importNaverList': 'Naver Seznam',
'places.googleListHint': 'Vložte sdílený odkaz na seznam Google Maps pro import všech míst.',
'places.googleListImported': '{count} míst importováno ze seznamu "{list}"',
'places.googleListError': 'Import seznamu Google Maps se nezdařil',
'places.naverListHint': 'Vložte sdílený odkaz na seznam Naver Maps pro import všech míst.',
'places.naverListImported': '{count} míst importováno ze seznamu "{list}"',
'places.naverListError': 'Import seznamu Naver Maps se nezdařil',
'places.viewDetails': 'Zobrazit detaily',
'places.assignToDay': 'Přidat do kterého dne?',
'places.all': 'Vše',
@@ -1665,6 +1670,7 @@ const cs: Record<string, string | { name: string; category: string }[]> = {
'undo.lock': 'Zámek místa přepnut',
'undo.importGpx': 'Import GPX',
'undo.importGoogleList': 'Import z Google Maps',
'undo.importNaverList': 'Import z Naver Maps',
// Notifications
'notifications.title': 'Oznámení',
+5
View File
@@ -897,10 +897,14 @@ const de: Record<string, string | { name: string; category: string }[]> = {
'places.gpxImported': '{count} Orte aus GPX importiert',
'places.urlResolved': 'Ort aus URL importiert',
'places.gpxError': 'GPX-Import fehlgeschlagen',
'places.importList': 'Listenimport',
'places.importGoogleList': 'Google Liste',
'places.googleListHint': 'Geteilten Google Maps Listen-Link einfügen, um alle Orte zu importieren.',
'places.googleListImported': '{count} Orte aus "{list}" importiert',
'places.googleListError': 'Google Maps Liste konnte nicht importiert werden',
'places.naverListHint': 'Geteilten Naver Maps Listen-Link einfügen, um alle Orte zu importieren.',
'places.naverListImported': '{count} Orte aus "{list}" importiert',
'places.naverListError': 'Naver Maps Liste konnte nicht importiert werden',
'places.viewDetails': 'Details anzeigen',
'places.assignToDay': 'Zu welchem Tag hinzufügen?',
'places.all': 'Alle',
@@ -1670,6 +1674,7 @@ const de: Record<string, string | { name: string; category: string }[]> = {
'undo.lock': 'Ortssperre umgeschaltet',
'undo.importGpx': 'GPX-Import',
'undo.importGoogleList': 'Google Maps-Import',
'undo.importNaverList': 'Naver Maps-Import',
// Notifications
'notifications.title': 'Benachrichtigungen',
+6
View File
@@ -919,10 +919,15 @@ const en: Record<string, string | { name: string; category: string }[]> = {
'places.gpxImported': '{count} places imported from GPX',
'places.urlResolved': 'Place imported from URL',
'places.gpxError': 'GPX import failed',
'places.importList': 'List Import',
'places.importGoogleList': 'Google List',
'places.importNaverList': 'Naver List',
'places.googleListHint': 'Paste a shared Google Maps list link to import all places.',
'places.googleListImported': '{count} places imported from "{list}"',
'places.googleListError': 'Failed to import Google Maps list',
'places.naverListHint': 'Paste a shared Naver Maps list link to import all places.',
'places.naverListImported': '{count} places imported from "{list}"',
'places.naverListError': 'Failed to import Naver Maps list',
'places.viewDetails': 'View Details',
'places.assignToDay': 'Add to which day?',
'places.all': 'All',
@@ -1704,6 +1709,7 @@ const en: Record<string, string | { name: string; category: string }[]> = {
'undo.lock': 'Place lock toggled',
'undo.importGpx': 'GPX import',
'undo.importGoogleList': 'Google Maps import',
'undo.importNaverList': 'Naver Maps import',
'undo.addPlace': 'Place added',
'undo.done': 'Undone: {action}',
+5
View File
@@ -868,10 +868,14 @@ const es: Record<string, string> = {
'places.importGpx': 'GPX',
'places.gpxImported': '{count} lugares importados desde GPX',
'places.gpxError': 'Error al importar GPX',
'places.importList': 'Importar lista',
'places.importGoogleList': 'Lista Google',
'places.googleListHint': 'Pega un enlace compartido de una lista de Google Maps para importar todos los lugares.',
'places.googleListImported': '{count} lugares importados de "{list}"',
'places.googleListError': 'Error al importar la lista de Google Maps',
'places.naverListHint': 'Pega un enlace compartido de una lista de Naver Maps para importar todos los lugares.',
'places.naverListImported': '{count} lugares importados de "{list}"',
'places.naverListError': 'Error al importar la lista de Naver Maps',
'places.viewDetails': 'Ver detalles',
'places.urlResolved': 'Lugar importado desde URL',
'places.assignToDay': '¿A qué día añadirlo?',
@@ -1672,6 +1676,7 @@ const es: Record<string, string> = {
'undo.lock': 'Bloqueo de lugar activado/desactivado',
'undo.importGpx': 'Importación GPX',
'undo.importGoogleList': 'Importación de Google Maps',
'undo.importNaverList': 'Importación de Naver Maps',
// Notifications
'notifications.title': 'Notificaciones',
+6
View File
@@ -892,10 +892,15 @@ const fr: Record<string, string> = {
'places.importGpx': 'GPX',
'places.gpxImported': '{count} lieux importés depuis GPX',
'places.gpxError': 'L\'import GPX a échoué',
'places.importList': 'Import de liste',
'places.importGoogleList': 'Liste Google',
'places.importNaverList': 'Liste Naver',
'places.googleListHint': 'Collez un lien de liste Google Maps partagée pour importer tous les lieux.',
'places.googleListImported': '{count} lieux importés depuis "{list}"',
'places.googleListError': 'Impossible d\'importer la liste Google Maps',
'places.naverListHint': 'Collez un lien de liste Naver Maps partagée pour importer tous les lieux.',
'places.naverListImported': '{count} lieux importés depuis "{list}"',
'places.naverListError': 'Impossible d\'importer la liste Naver Maps',
'places.viewDetails': 'Voir les détails',
'places.urlResolved': 'Lieu importé depuis l\'URL',
'places.assignToDay': 'Ajouter à quel jour ?',
@@ -1666,6 +1671,7 @@ const fr: Record<string, string> = {
'undo.lock': 'Verrouillage du lieu modifié',
'undo.importGpx': 'Import GPX',
'undo.importGoogleList': 'Import Google Maps',
'undo.importNaverList': 'Import Naver Maps',
// Notifications
'notifications.title': 'Notifications',
+6
View File
@@ -894,10 +894,15 @@ const hu: Record<string, string | { name: string; category: string }[]> = {
'places.gpxImported': '{count} hely importálva GPX-ből',
'places.urlResolved': 'Hely importálva URL-ből',
'places.gpxError': 'GPX importálás sikertelen',
'places.importList': 'Lista importálás',
'places.importGoogleList': 'Google Lista',
'places.importNaverList': 'Naver Lista',
'places.googleListHint': 'Illessz be egy megosztott Google Maps lista linket az osszes hely importalasahoz.',
'places.googleListImported': '{count} hely importalva a(z) "{list}" listabol',
'places.googleListError': 'Google Maps lista importalasa sikertelen',
'places.naverListHint': 'Illessz be egy megosztott Naver Maps lista linket az összes hely importálásához.',
'places.naverListImported': '{count} hely importálva a(z) "{list}" listából',
'places.naverListError': 'Naver Maps lista importálása sikertelen',
'places.viewDetails': 'Részletek megtekintése',
'places.assignToDay': 'Melyik naphoz adod?',
'places.all': 'Összes',
@@ -1664,6 +1669,7 @@ const hu: Record<string, string | { name: string; category: string }[]> = {
'undo.lock': 'Hely zárolása váltva',
'undo.importGpx': 'GPX importálás',
'undo.importGoogleList': 'Google Maps importálás',
'undo.importNaverList': 'Naver Maps importálás',
// Notifications
'notifications.title': 'Értesítések',
+6
View File
@@ -894,10 +894,15 @@ const it: Record<string, string | { name: string; category: string }[]> = {
'places.gpxImported': '{count} luoghi importati da GPX',
'places.urlResolved': 'Luogo importato dall\'URL',
'places.gpxError': 'Importazione GPX non riuscita',
'places.importList': 'Importa lista',
'places.importGoogleList': 'Lista Google',
'places.importNaverList': 'Lista Naver',
'places.googleListHint': 'Incolla un link condiviso di una lista Google Maps per importare tutti i luoghi.',
'places.googleListImported': '{count} luoghi importati da "{list}"',
'places.googleListError': 'Importazione lista Google Maps non riuscita',
'places.naverListHint': 'Incolla un link condiviso di una lista Naver Maps per importare tutti i luoghi.',
'places.naverListImported': '{count} luoghi importati da "{list}"',
'places.naverListError': 'Importazione lista Naver Maps non riuscita',
'places.viewDetails': 'Visualizza dettagli',
'places.assignToDay': 'A quale giorno aggiungere?',
'places.all': 'Tutti',
@@ -1668,6 +1673,7 @@ const it: Record<string, string | { name: string; category: string }[]> = {
'undo.lock': 'Blocco luogo modificato',
'undo.importGpx': 'Importazione GPX',
'undo.importGoogleList': 'Importazione Google Maps',
'undo.importNaverList': 'Importazione Naver Maps',
'undo.addPlace': 'Luogo aggiunto',
'undo.done': 'Annullato: {action}',
// Notifications
+6
View File
@@ -892,10 +892,15 @@ const nl: Record<string, string> = {
'places.importGpx': 'GPX',
'places.gpxImported': '{count} plaatsen geïmporteerd uit GPX',
'places.gpxError': 'GPX-import mislukt',
'places.importList': 'Lijst importeren',
'places.importGoogleList': 'Google Lijst',
'places.importNaverList': 'Naver Lijst',
'places.googleListHint': 'Plak een gedeelde Google Maps lijstlink om alle plaatsen te importeren.',
'places.googleListImported': '{count} plaatsen geimporteerd uit "{list}"',
'places.googleListError': 'Google Maps lijst importeren mislukt',
'places.naverListHint': 'Plak een gedeelde Naver Maps lijstlink om alle plaatsen te importeren.',
'places.naverListImported': '{count} plaatsen geimporteerd uit "{list}"',
'places.naverListError': 'Naver Maps lijst importeren mislukt',
'places.viewDetails': 'Details bekijken',
'places.urlResolved': 'Plaats geïmporteerd van URL',
'places.assignToDay': 'Aan welke dag toevoegen?',
@@ -1666,6 +1671,7 @@ const nl: Record<string, string> = {
'undo.lock': 'Vergrendeling locatie gewijzigd',
'undo.importGpx': 'GPX-import',
'undo.importGoogleList': 'Google Maps-import',
'undo.importNaverList': 'Naver Maps-import',
// Notifications
'notifications.title': 'Meldingen',
+6
View File
@@ -1609,9 +1609,14 @@ const pl: Record<string, string | { name: string; category: string }[]> = {
'atlas.searchCountry': 'Szukaj kraju...',
'trip.loadingPhotos': 'Ładowanie zdjęć...',
'places.importGoogleList': 'Lista Google',
'places.importNaverList': 'Lista Naver',
'places.importList': 'Import listy',
'places.googleListHint': 'Wklej link do listy Google Maps.',
'places.googleListImported': 'Zaimportowano {count} miejsc',
'places.googleListError': 'Nie udało się zaimportować listy',
'places.naverListHint': 'Wklej link do udostępnionej listy Naver Maps, aby zaimportować wszystkie miejsca.',
'places.naverListImported': 'Zaimportowano {count} miejsc z "{list}"',
'places.naverListError': 'Nie udało się zaimportować listy Naver Maps',
'places.viewDetails': 'Zobacz szczegóły',
'inspector.trackStats': 'Statystyki trasy',
'budget.exportCsv': 'Eksportuj CSV',
@@ -1691,6 +1696,7 @@ const pl: Record<string, string | { name: string; category: string }[]> = {
'undo.lock': 'Blokada przełączona',
'undo.importGpx': 'Import GPX',
'undo.importGoogleList': 'Import Google Maps',
'undo.importNaverList': 'Import Naver Maps',
'undo.addPlace': 'Miejsce dodane',
'undo.done': 'Cofnięto: {action}',
'notifications.title': 'Powiadomienia',
+6
View File
@@ -892,10 +892,15 @@ const ru: Record<string, string> = {
'places.importGpx': 'GPX',
'places.gpxImported': '{count} мест импортировано из GPX',
'places.gpxError': 'Ошибка импорта GPX',
'places.importList': 'Импорт списка',
'places.importGoogleList': 'Список Google',
'places.importNaverList': 'Список Naver',
'places.googleListHint': 'Вставьте ссылку на общий список Google Maps для импорта всех мест.',
'places.googleListImported': '{count} мест импортировано из "{list}"',
'places.googleListError': 'Не удалось импортировать список Google Maps',
'places.naverListHint': 'Вставьте ссылку на общий список Naver Maps для импорта всех мест.',
'places.naverListImported': '{count} мест импортировано из "{list}"',
'places.naverListError': 'Не удалось импортировать список Naver Maps',
'places.viewDetails': 'Подробности',
'places.urlResolved': 'Место импортировано из URL',
'places.assignToDay': 'Добавить в какой день?',
@@ -1663,6 +1668,7 @@ const ru: Record<string, string> = {
'undo.lock': 'Блокировка места изменена',
'undo.importGpx': 'Импорт GPX',
'undo.importGoogleList': 'Импорт из Google Maps',
'undo.importNaverList': 'Импорт из Naver Maps',
// Notifications
'notifications.title': 'Уведомления',
+6
View File
@@ -892,10 +892,15 @@ const zh: Record<string, string> = {
'places.importGpx': 'GPX',
'places.gpxImported': '已从 GPX 导入 {count} 个地点',
'places.gpxError': 'GPX 导入失败',
'places.importList': '列表导入',
'places.importGoogleList': 'Google 列表',
'places.importNaverList': 'Naver 列表',
'places.googleListHint': '粘贴共享的 Google Maps 列表链接以导入所有地点。',
'places.googleListImported': '已从"{list}"导入 {count} 个地点',
'places.googleListError': 'Google Maps 列表导入失败',
'places.naverListHint': '粘贴共享的 Naver Maps 列表链接以导入所有地点。',
'places.naverListImported': '已从"{list}"导入 {count} 个地点',
'places.naverListError': 'Naver Maps 列表导入失败',
'places.viewDetails': '查看详情',
'places.urlResolved': '已从 URL 导入地点',
'places.assignToDay': '添加到哪一天?',
@@ -1663,6 +1668,7 @@ const zh: Record<string, string> = {
'undo.lock': '地点锁定已切换',
'undo.importGpx': 'GPX 导入',
'undo.importGoogleList': 'Google 地图导入',
'undo.importNaverList': 'Naver 地图导入',
// Notifications
'notifications.title': '通知',
+6
View File
@@ -917,10 +917,15 @@ const zhTw: Record<string, string> = {
'places.importGpx': 'GPX',
'places.gpxImported': '已從 GPX 匯入 {count} 個地點',
'places.gpxError': 'GPX 匯入失敗',
'places.importList': '列表匯入',
'places.importGoogleList': 'Google 列表',
'places.importNaverList': 'Naver 列表',
'places.googleListHint': '貼上共享的 Google Maps 列表連結以匯入所有地點。',
'places.googleListImported': '已從"{list}"匯入 {count} 個地點',
'places.googleListError': 'Google Maps 列表匯入失敗',
'places.naverListHint': '貼上共享的 Naver Maps 列表連結以匯入所有地點。',
'places.naverListImported': '已從"{list}"匯入 {count} 個地點',
'places.naverListError': 'Naver Maps 列表匯入失敗',
'places.viewDetails': '檢視詳情',
'places.urlResolved': '已從 URL 匯入地點',
'places.assignToDay': '新增到哪一天?',
@@ -1688,6 +1693,7 @@ const zhTw: Record<string, string> = {
'undo.lock': '地點鎖定已切換',
'undo.importGpx': 'GPX 匯入',
'undo.importGoogleList': 'Google 地圖匯入',
'undo.importNaverList': 'Naver 地圖匯入',
// Todo
'todo.subtab.packing': '行李清單',