mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
feat(notices): bring the release notes back on every update
The release modal takes the 4.3.0 design: the release and its headline cards on the left, the note and the support links on the right, at the design's own size. The cards carry small drawings of the features instead of an icon. The 4.0.0 entry is retired. In its place sits one entry, release-notes, that every big release rewrites and keeps. It recurs per version with no upper bound, so every user sees it once on each update, whatever they did with it before, and a reload of the same version keeps it closed. An integration test holds that promise through the real entry and the real dismiss route. All 23 locales carry the new copy and drop the 4.0.0 strings.
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
// FE-RN-001 to FE-RN-011
|
||||
// FE-RN-001 to FE-RN-014
|
||||
import { describe, it, expect, vi } from 'vitest'
|
||||
import { render, screen } from '../../../tests/helpers/render'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { ReleaseNoticeModal } from './ReleaseNoticeModal'
|
||||
import type { SystemNoticeDTO } from '../../store/systemNoticeStore'
|
||||
|
||||
/** A notice shaped like the 4.0.0 registry entry, with the pieces a test needs to vary. */
|
||||
/** A notice shaped like the release-notes registry entry, with the pieces a test needs to vary. */
|
||||
function releaseNotice(overrides: Partial<SystemNoticeDTO> = {}): SystemNoticeDTO {
|
||||
return {
|
||||
id: 'release-4-0-0',
|
||||
id: 'release-notes',
|
||||
display: 'modal',
|
||||
severity: 'info',
|
||||
titleKey: 'rel.headline',
|
||||
@@ -18,25 +18,27 @@ function releaseNotice(overrides: Partial<SystemNoticeDTO> = {}): SystemNoticeDT
|
||||
cta: { kind: 'link', labelKey: 'rel.bmc', href: 'https://buymeacoffee.com/mauriceboe' },
|
||||
secondaryCta: { kind: 'link', labelKey: 'rel.kofi', href: 'https://ko-fi.com/mauriceboe' },
|
||||
release: {
|
||||
version: '4.0.0',
|
||||
version: '4.3.0',
|
||||
eyebrowKey: 'rel.eyebrow',
|
||||
tagKey: 'rel.tag',
|
||||
headlineKey: 'rel.headline',
|
||||
introKey: 'rel.intro',
|
||||
featuresLabelKey: 'rel.features.label',
|
||||
features: [
|
||||
{ iconName: 'Smartphone', titleKey: 'rel.f1.title', bodyKey: 'rel.f1.body' },
|
||||
{ iconName: 'BookOpen', titleKey: 'rel.f2.title', bodyKey: 'rel.f2.body', badgeKey: 'rel.f2.badge' },
|
||||
{ iconName: 'Database', visual: 'places-api', titleKey: 'rel.f1.title', bodyKey: 'rel.f1.body' },
|
||||
{ iconName: 'Route', visual: 'roadtrip', titleKey: 'rel.f2.title', bodyKey: 'rel.f2.body' },
|
||||
{ iconName: 'MapPin', visual: 'dawarich', titleKey: 'rel.f3.title', bodyKey: 'rel.f3.body' },
|
||||
],
|
||||
note: {
|
||||
eyebrowKey: 'rel.note.eyebrow',
|
||||
titleKey: 'rel.note.title',
|
||||
bodyKey: 'rel.note.body',
|
||||
promiseLabelKey: 'rel.promise.label',
|
||||
promiseLeadKey: 'rel.promise.lead',
|
||||
promiseTextKey: 'rel.promise.text',
|
||||
bodyAfterKey: 'rel.note.after',
|
||||
closingKey: 'rel.note.closing',
|
||||
signatureKey: 'rel.note.signature',
|
||||
},
|
||||
supportLeadKey: 'rel.support.lead',
|
||||
supportTextKey: 'rel.support',
|
||||
},
|
||||
...overrides,
|
||||
@@ -69,14 +71,16 @@ describe('ReleaseNoticeModal', () => {
|
||||
|
||||
it('FE-RN-002: shows the version as a plain figure, not a translation key', () => {
|
||||
renderModal()
|
||||
expect(screen.getByText('4.0.0')).toBeInTheDocument()
|
||||
expect(screen.getByText('4.3.0')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('FE-RN-003: renders one row per feature, with the badge only where declared', () => {
|
||||
it('FE-RN-003: renders one card per feature, each with its drawing', () => {
|
||||
renderModal()
|
||||
expect(screen.getByText('rel.f1.title')).toBeInTheDocument()
|
||||
expect(screen.getByText('rel.f2.badge')).toBeInTheDocument()
|
||||
expect(document.querySelectorAll('.rn-feature')).toHaveLength(2)
|
||||
expect(document.querySelectorAll('.rn-feature')).toHaveLength(3)
|
||||
expect(document.querySelector('.rn-vis-places')).not.toBeNull()
|
||||
expect(document.querySelector('.rn-vis-road')).not.toBeNull()
|
||||
expect(document.querySelector('.rn-vis-trail')).not.toBeNull()
|
||||
})
|
||||
|
||||
it('FE-RN-004: splits the note body on the blank line into separate paragraphs', () => {
|
||||
@@ -88,17 +92,17 @@ describe('ReleaseNoticeModal', () => {
|
||||
expect(screen.getByText('second paragraph')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('FE-RN-005: omits the stats row when the release carries no stats', () => {
|
||||
it('FE-RN-005: omits the foot when the release has neither a footnote nor notes', () => {
|
||||
renderModal()
|
||||
expect(document.querySelector('.rn-release-foot')).toBeNull()
|
||||
})
|
||||
|
||||
it('FE-RN-006: shows the stats row and the notes link when both are present', () => {
|
||||
it('FE-RN-006: shows the footnote and the notes link when both are present', () => {
|
||||
const n = releaseNotice()
|
||||
n.release!.stats = [{ value: '~150', labelKey: 'rel.stat.bugs' }]
|
||||
n.release!.footnoteKey = 'rel.footnote'
|
||||
n.release!.notes = { labelKey: 'rel.notes', href: 'https://example.test/notes' }
|
||||
renderModal(n)
|
||||
expect(screen.getByText('~150')).toBeInTheDocument()
|
||||
expect(screen.getByText('rel.footnote')).toBeInTheDocument()
|
||||
const link = screen.getByRole('link', { name: /rel\.notes/ })
|
||||
expect(link).toHaveAttribute('href', 'https://example.test/notes')
|
||||
expect(link).toHaveAttribute('target', '_blank')
|
||||
@@ -152,9 +156,37 @@ describe('ReleaseNoticeModal', () => {
|
||||
renderModal()
|
||||
const dialog = screen.getByRole('dialog')
|
||||
expect(dialog).toHaveAttribute('aria-modal', 'true')
|
||||
expect(dialog).toHaveAttribute('aria-labelledby', 'notice-title-release-4-0-0')
|
||||
expect(dialog).toHaveAttribute('aria-describedby', 'notice-body-release-4-0-0')
|
||||
expect(document.getElementById('notice-title-release-4-0-0')).toHaveTextContent('rel.headline')
|
||||
expect(document.getElementById('notice-body-release-4-0-0')).toHaveTextContent('rel.intro')
|
||||
expect(dialog).toHaveAttribute('aria-labelledby', 'notice-title-release-notes')
|
||||
expect(dialog).toHaveAttribute('aria-describedby', 'notice-body-release-notes')
|
||||
expect(document.getElementById('notice-title-release-notes')).toHaveTextContent('rel.headline')
|
||||
expect(document.getElementById('notice-body-release-notes')).toHaveTextContent('rel.intro')
|
||||
})
|
||||
|
||||
it('FE-RN-012: sets the promise and the support text with a bold lead', () => {
|
||||
renderModal()
|
||||
expect(screen.getByText('rel.promise.lead').tagName).toBe('B')
|
||||
expect(screen.getByText('rel.support.lead').tagName).toBe('B')
|
||||
expect(screen.getByText('rel.promise.text')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('FE-RN-013: the features aside is optional', () => {
|
||||
renderModal()
|
||||
expect(document.querySelector('.rn-features-aside')).toBeNull()
|
||||
|
||||
const n = releaseNotice()
|
||||
n.release!.featuresAsideKey = 'rel.features.aside'
|
||||
renderModal(n)
|
||||
expect(screen.getByText('rel.features.aside')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('FE-RN-014: a card whose drawing this client does not know falls back to its icon', () => {
|
||||
const n = releaseNotice()
|
||||
n.release!.features = [
|
||||
{ iconName: 'Route', visual: 'from-a-newer-server', titleKey: 'rel.x.title', bodyKey: 'rel.x.body' },
|
||||
{ iconName: 'NoSuchIcon', titleKey: 'rel.y.title', bodyKey: 'rel.y.body' },
|
||||
]
|
||||
renderModal(n)
|
||||
expect(document.querySelectorAll('.rn-vis-icon')).toHaveLength(2)
|
||||
expect(document.querySelectorAll('.rn-vis-icon svg')).toHaveLength(2)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import * as LucideIcons from 'lucide-react';
|
||||
import { ArrowRight, Coffee, Heart, Infinity as InfinityIcon, Sparkles, X } from 'lucide-react';
|
||||
import { ArrowRight, Heart, Infinity as InfinityIcon, X } from 'lucide-react';
|
||||
import { useTranslation } from '../../i18n/TranslationContext.js';
|
||||
import type { SystemNoticeDTO } from '../../store/systemNoticeStore.js';
|
||||
import { ReleaseFeatureVisual } from './ReleaseNoticeVisuals.js';
|
||||
import './releaseNotice.css';
|
||||
|
||||
interface Props {
|
||||
@@ -13,6 +13,20 @@ interface Props {
|
||||
onSecondaryCTA: () => void;
|
||||
}
|
||||
|
||||
/** Lucide's coffee cup, drawn here so its three steam strokes can drift up in waves. */
|
||||
function SteamingCoffee() {
|
||||
return (
|
||||
<svg className="rn-coffee" width={18} height={18} viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
strokeWidth={2.1} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
||||
<path d="M17 8h1a4 4 0 1 1 0 8h-1" />
|
||||
<path d="M3 8h14v9a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4Z" />
|
||||
<path className="rn-steam" d="M6 5.5c-1.2-.9 1.2-1.7 0-2.6s1.2-1.7 0-2.6 1.2-1.7 0-2.6" />
|
||||
<path className="rn-steam" d="M10 5.5c-1.2-.9 1.2-1.7 0-2.6s1.2-1.7 0-2.6 1.2-1.7 0-2.6" />
|
||||
<path className="rn-steam" d="M14 5.5c-1.2-.9 1.2-1.7 0-2.6s1.2-1.7 0-2.6 1.2-1.7 0-2.6" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
/** Splits a translated block into paragraphs the way the notice bodies are written. */
|
||||
function paragraphs(text: string): string[] {
|
||||
return text.split('\n\n').map(p => p.trim()).filter(Boolean);
|
||||
@@ -21,10 +35,10 @@ function paragraphs(text: string): string[] {
|
||||
/**
|
||||
* The release modal: what shipped on the left, a note from the maintainer on
|
||||
* the right. Rendered instead of the generic notice body whenever a notice
|
||||
* carries `release` — every string comes from that block, so a later release
|
||||
* only edits the registry entry.
|
||||
* carries `release`. Every string comes from that block, so a later release
|
||||
* only edits the registry entry and its keys.
|
||||
*
|
||||
* Desktop only (the notices carrying it set `desktopOnly`), and it keeps the
|
||||
* Desktop only (the notice carrying it sets `desktopOnly`), and it keeps the
|
||||
* generic modal's behaviour: the host hook still owns ESC, the scroll lock and
|
||||
* the dismissal, this component only draws.
|
||||
*/
|
||||
@@ -62,48 +76,37 @@ export function ReleaseNoticeModal({ notice, visible, onDismiss, onCTA, onSecond
|
||||
<span className="rn-eyebrow">{t(release.eyebrowKey)}</span>
|
||||
</div>
|
||||
|
||||
<div className="rn-version-row">
|
||||
<div className="rn-version">{release.version}</div>
|
||||
<div className="rn-tag">{t(release.tagKey)}</div>
|
||||
</div>
|
||||
<div className="rn-version">{release.version}</div>
|
||||
|
||||
<h2 id={titleId} className="rn-headline">{t(release.headlineKey)}</h2>
|
||||
<p id={bodyId} className="rn-intro">{t(release.introKey)}</p>
|
||||
|
||||
<div className="rn-features">
|
||||
{release.features.map(f => {
|
||||
const Icon: React.ElementType =
|
||||
((LucideIcons as Record<string, unknown>)[f.iconName] as React.ElementType) ?? Sparkles;
|
||||
return (
|
||||
<div key={f.titleKey} className="rn-feature">
|
||||
<span className="rn-feature-icon">
|
||||
<Icon size={18} strokeWidth={1.9} aria-hidden="true" />
|
||||
</span>
|
||||
<div className="rn-feature-text">
|
||||
<div className="rn-feature-title">
|
||||
{t(f.titleKey)}
|
||||
{f.badgeKey && <span className="rn-badge">{t(f.badgeKey)}</span>}
|
||||
</div>
|
||||
<div className="rn-feature-body">{t(f.bodyKey)}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<div className="rn-features-head">
|
||||
<span className="rn-features-label">{t(release.featuresLabelKey)}</span>
|
||||
<span className="rn-features-rule" aria-hidden="true" />
|
||||
{release.featuresAsideKey && (
|
||||
<span className="rn-features-aside">{t(release.featuresAsideKey)}</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{((release.stats?.length ?? 0) > 0 || release.notes) && (
|
||||
<div className="rn-release-foot">
|
||||
{release.stats && release.stats.length > 0 && (
|
||||
<div className="rn-stats">
|
||||
{release.stats.map(s => (
|
||||
<div key={s.labelKey}>
|
||||
<div className="rn-stat-value">{s.value}</div>
|
||||
<div className="rn-stat-label">{t(s.labelKey)}</div>
|
||||
</div>
|
||||
))}
|
||||
<div className="rn-features">
|
||||
{release.features.map(f => (
|
||||
<div key={f.titleKey} className="rn-feature">
|
||||
<div className="rn-feature-shine" aria-hidden="true" />
|
||||
<div className="rn-feature-visual" aria-hidden="true">
|
||||
<ReleaseFeatureVisual visual={f.visual} iconName={f.iconName} />
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<div className="rn-feature-title">{t(f.titleKey)}</div>
|
||||
<div className="rn-feature-body">{t(f.bodyKey)}</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{(release.footnoteKey || release.notes) && (
|
||||
<div className="rn-release-foot">
|
||||
<div className="rn-footnote">{release.footnoteKey ? t(release.footnoteKey) : null}</div>
|
||||
{release.notes && (
|
||||
<a
|
||||
className="rn-notes"
|
||||
@@ -119,10 +122,6 @@ export function ReleaseNoticeModal({ notice, visible, onDismiss, onCTA, onSecond
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{release.footnoteKey && (
|
||||
<div className="rn-footnote">{t(release.footnoteKey)}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -130,7 +129,7 @@ export function ReleaseNoticeModal({ notice, visible, onDismiss, onCTA, onSecond
|
||||
<div className="rn-note">
|
||||
{notice.dismissible && (
|
||||
<button type="button" className="rn-close" onClick={onDismiss} aria-label={t('common.close')}>
|
||||
<X size={18} strokeWidth={2} />
|
||||
<X size={17} strokeWidth={2} />
|
||||
</button>
|
||||
)}
|
||||
|
||||
@@ -145,19 +144,21 @@ export function ReleaseNoticeModal({ notice, visible, onDismiss, onCTA, onSecond
|
||||
<InfinityIcon size={14} strokeWidth={2.1} aria-hidden="true" />
|
||||
{t(release.note.promiseLabelKey)}
|
||||
</div>
|
||||
<div className="rn-promise-text">{t(release.note.promiseTextKey)}</div>
|
||||
<div className="rn-promise-text">
|
||||
<b>{t(release.note.promiseLeadKey)}</b>{' '}
|
||||
<span>{t(release.note.promiseTextKey)}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{paragraphs(t(release.note.bodyAfterKey)).map((p, i) => <p key={i}>{p}</p>)}
|
||||
|
||||
<div className="rn-signoff">
|
||||
<div className="rn-closing">{t(release.note.closingKey)}</div>
|
||||
<div className="rn-signature">{t(release.note.signatureKey)}</div>
|
||||
</div>
|
||||
<div className="rn-closing">{t(release.note.closingKey)}</div>
|
||||
</div>
|
||||
|
||||
<div className="rn-support">
|
||||
<div className="rn-support-text">{t(release.supportTextKey)}</div>
|
||||
<div className="rn-support-text">
|
||||
<b>{t(release.supportLeadKey)}</b> {t(release.supportTextKey)}
|
||||
</div>
|
||||
<div className="rn-support-buttons">
|
||||
{notice.cta && (
|
||||
<button type="button"
|
||||
@@ -165,7 +166,7 @@ export function ReleaseNoticeModal({ notice, visible, onDismiss, onCTA, onSecond
|
||||
className="rn-support-btn rn-support-bmc"
|
||||
onClick={onCTA}
|
||||
>
|
||||
<Coffee size={18} strokeWidth={2.1} aria-hidden="true" />
|
||||
<SteamingCoffee />
|
||||
{t(notice.cta.labelKey)}
|
||||
</button>
|
||||
)}
|
||||
@@ -175,7 +176,7 @@ export function ReleaseNoticeModal({ notice, visible, onDismiss, onCTA, onSecond
|
||||
className="rn-support-btn rn-support-kofi"
|
||||
onClick={onSecondaryCTA}
|
||||
>
|
||||
<Heart size={18} strokeWidth={2.1} aria-hidden="true" />
|
||||
<Heart className="rn-heart" size={18} strokeWidth={2.1} aria-hidden="true" />
|
||||
{t(notice.secondaryCta.labelKey)}
|
||||
</button>
|
||||
)}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
import React from 'react';
|
||||
import * as LucideIcons from 'lucide-react';
|
||||
import { Car, Landmark, Search, Sparkles } from 'lucide-react';
|
||||
import DawarichIcon from '../shared/DawarichIcon';
|
||||
import TrekMark from '../shared/TrekMark';
|
||||
|
||||
/*
|
||||
* The small pictures on the release cards: pieces of TREK itself, drawn at card
|
||||
* size rather than screenshotted, because a screenshot this small is a blur. They
|
||||
* carry no words, only place names and figures that read the same in every
|
||||
* language, so nothing here needs translating.
|
||||
*/
|
||||
|
||||
function PlacesApiVisual() {
|
||||
return (
|
||||
<div className="rn-vis rn-vis-places">
|
||||
<span className="rn-vis-trekbadge"><TrekMark className="rn-vis-trekmark" /></span>
|
||||
<div className="rn-vis-search">
|
||||
<Search size={11} strokeWidth={2.4} />
|
||||
<span className="rn-vis-typed">Fushimi Inari</span>
|
||||
<span className="rn-vis-caret" />
|
||||
</div>
|
||||
<div className="rn-vis-result">
|
||||
<span className="rn-vis-cat" style={{ background: '#ef4444' }}><Landmark size={10} strokeWidth={2.2} /></span>
|
||||
<span className="rn-vis-place">
|
||||
<span>Fushimi Inari Taisha</span>
|
||||
<small>Kyoto</small>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// The route and its stops, in the planner's own route blue and marker style.
|
||||
const ROUTE = 'M26 84 C 58 82, 60 44, 96 46 S 136 74, 160 52 S 176 30, 182 28';
|
||||
|
||||
function RoadtripVisual() {
|
||||
return (
|
||||
<div className="rn-vis rn-vis-road">
|
||||
<svg viewBox="0 0 200 112" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
|
||||
<path className="rn-vis-road-casing" d={ROUTE} />
|
||||
<path className="rn-vis-road-line" d={ROUTE} />
|
||||
</svg>
|
||||
<span className="rn-vis-marker" style={{ left: '13%', top: '75%', background: '#6366f1' }}>1</span>
|
||||
<span className="rn-vis-marker" style={{ left: '48%', top: '41%', background: '#f59e0b' }}>2</span>
|
||||
<span className="rn-vis-marker" style={{ left: '91%', top: '25%', background: '#ec4899' }}>3</span>
|
||||
<span className="rn-vis-distance"><Car size={10} strokeWidth={2.2} />386 km</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// A recorded day, with the two places the traveller stayed.
|
||||
const TRAIL = '84,94 96,88 106,80 118,76 130,74 142,66 152,58 162,62 172,66 180,56 186,46';
|
||||
const STAYS: Array<[number, number]> = [[130, 74], [186, 46]];
|
||||
|
||||
function DawarichVisual() {
|
||||
return (
|
||||
<div className="rn-vis rn-vis-trail">
|
||||
<svg viewBox="0 0 200 112" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
|
||||
<polyline className="rn-vis-trail-line" points={TRAIL} />
|
||||
{STAYS.map(([x, y]) => <circle key={x} className="rn-vis-trail-stay" cx={x} cy={y} r="3.4" />)}
|
||||
</svg>
|
||||
<span className="rn-vis-brand"><DawarichIcon size={58} /></span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const VISUALS: Record<string, () => React.ReactElement> = {
|
||||
'places-api': PlacesApiVisual,
|
||||
roadtrip: RoadtripVisual,
|
||||
dawarich: DawarichVisual,
|
||||
};
|
||||
|
||||
/** The card's picture, or its icon when the release names no drawing this client knows. */
|
||||
export function ReleaseFeatureVisual({ visual, iconName }: { visual?: string; iconName: string }) {
|
||||
const Drawing = visual ? VISUALS[visual] : undefined;
|
||||
if (Drawing) return <Drawing />;
|
||||
const Icon: React.ElementType =
|
||||
((LucideIcons as Record<string, unknown>)[iconName] as React.ElementType) ?? Sparkles;
|
||||
return (
|
||||
<div className="rn-vis rn-vis-icon">
|
||||
<Icon size={30} strokeWidth={1.6} aria-hidden="true" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,22 +1,18 @@
|
||||
/*
|
||||
* The release notice modal — a two-column panel: the release on the left,
|
||||
* a note from the maintainer on the right.
|
||||
* The release notice modal: a two-column panel, the release on the left and a
|
||||
* note from the maintainer on the right.
|
||||
*
|
||||
* The measurements here are the design's own, kept in one stylesheet rather
|
||||
* than spread across inline styles (the same arrangement mobile.css uses for
|
||||
* the mobile shell). Every one of them is multiplied by --rn-s, so the whole
|
||||
* panel scales as one piece and the proportions never drift: change that one
|
||||
* number to resize the modal.
|
||||
* The measurements are the design's own, at full size, kept in one stylesheet
|
||||
* rather than spread across inline styles (the same arrangement mobile.css uses
|
||||
* for the mobile shell). The panel is 1420px wide wherever the screen has room
|
||||
* and gives up width, never size, where it has not.
|
||||
*
|
||||
* The left column is deliberately dark in both themes: it is a brand panel,
|
||||
* not a surface, so it does not read the surface tokens. Everything on the
|
||||
* right does.
|
||||
* The left column is deliberately dark in both themes: it is a brand panel, not
|
||||
* a surface, so it does not read the surface tokens. Everything on the right
|
||||
* does. theme-lint-disable: the brand panel's colours are fixed by design.
|
||||
*/
|
||||
|
||||
.rn-overlay {
|
||||
/* Design is drawn at 1420px wide; anything below full size is this factor. */
|
||||
--rn-s: 0.72;
|
||||
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
/* Above the navbar, the page-bound sticky bars and the page-owned
|
||||
@@ -25,22 +21,13 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 28px;
|
||||
padding: 34px;
|
||||
background: oklch(0.12 0.01 60 / 0.52);
|
||||
backdrop-filter: blur(14px) saturate(1.1);
|
||||
-webkit-backdrop-filter: blur(14px) saturate(1.1);
|
||||
animation: rn-fade 0.35s ease both;
|
||||
}
|
||||
|
||||
/* Roomy screens can carry a little more of the design's own scale. */
|
||||
@media (min-width: 1900px) and (min-height: 1150px) {
|
||||
.rn-overlay { --rn-s: 0.86; }
|
||||
}
|
||||
|
||||
@media (max-width: 1280px), (max-height: 760px) {
|
||||
.rn-overlay { --rn-s: 0.64; padding: 16px; }
|
||||
}
|
||||
|
||||
@keyframes rn-fade {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
@@ -51,18 +38,30 @@
|
||||
to { opacity: 1; transform: none; }
|
||||
}
|
||||
|
||||
/*
|
||||
* The design draws these boxes with their border outside the stated size, the
|
||||
* browser default. TREK sets border-box globally, which would take 2px off each.
|
||||
*/
|
||||
.rn-panel,
|
||||
.rn-mark,
|
||||
.rn-feature,
|
||||
.rn-feature-visual,
|
||||
.rn-notes,
|
||||
.rn-close { box-sizing: content-box; }
|
||||
|
||||
.rn-panel {
|
||||
width: calc(1420px * var(--rn-s));
|
||||
max-width: 100%;
|
||||
width: min(1420px, calc(100% - 2px));
|
||||
max-height: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: 1.3fr 1fr;
|
||||
border-radius: calc(34px * var(--rn-s));
|
||||
grid-template-columns: 1.2fr 1fr;
|
||||
border-radius: 30px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 12px oklch(0 0 0 / 0.2), 0 60px 130px -40px oklch(0 0 0 / 0.7);
|
||||
border: 1px solid oklch(1 0 0 / 0.1);
|
||||
animation: rn-rise 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
|
||||
font-family: var(--font-system);
|
||||
/* The design sets no base line height; the app's 1.5 would add 3px to every label. */
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
/* Below the two-column breakpoint the halves stack and the panel scrolls. */
|
||||
@@ -85,7 +84,7 @@
|
||||
position: relative;
|
||||
background: radial-gradient(120% 95% at 18% 0%, #1b1b22 0%, #0e0e12 52%, #08080a 100%);
|
||||
color: #f5f5f7;
|
||||
padding: calc(50px * var(--rn-s)) calc(54px * var(--rn-s)) calc(38px * var(--rn-s));
|
||||
padding: 44px 46px 34px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
@@ -110,14 +109,17 @@
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.rn-eyebrow-row { display: flex; align-items: center; gap: calc(11px * var(--rn-s)); }
|
||||
.rn-release-inner::-webkit-scrollbar { display: none; }
|
||||
|
||||
.rn-eyebrow-row { display: flex; align-items: center; gap: 11px; }
|
||||
|
||||
.rn-mark {
|
||||
width: calc(32px * var(--rn-s));
|
||||
height: calc(32px * var(--rn-s));
|
||||
border-radius: calc(10px * var(--rn-s));
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 10px;
|
||||
background: oklch(1 0 0 / 0.1);
|
||||
border: 1px solid oklch(1 0 0 / 0.16);
|
||||
display: flex;
|
||||
@@ -126,167 +128,156 @@
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.rn-mark img {
|
||||
width: calc(19px * var(--rn-s));
|
||||
height: calc(19px * var(--rn-s));
|
||||
display: block;
|
||||
}
|
||||
.rn-mark img { width: 18px; height: 18px; display: block; }
|
||||
|
||||
.rn-eyebrow {
|
||||
.rn-eyebrow,
|
||||
.rn-features-label {
|
||||
font-family: var(--font-subtext);
|
||||
font-size: calc(11.5px * var(--rn-s));
|
||||
font-size: 11px;
|
||||
line-height: 14px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.2em;
|
||||
text-transform: uppercase;
|
||||
color: oklch(1 0 0 / 0.5);
|
||||
}
|
||||
|
||||
.rn-version-row {
|
||||
margin-top: calc(30px * var(--rn-s));
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
gap: calc(20px * var(--rn-s));
|
||||
}
|
||||
|
||||
.rn-version {
|
||||
margin-top: 22px;
|
||||
font-family: var(--font-subtext);
|
||||
font-size: calc(112px * var(--rn-s));
|
||||
font-size: 74px;
|
||||
font-weight: 600;
|
||||
line-height: 0.82;
|
||||
line-height: 0.84;
|
||||
letter-spacing: -0.055em;
|
||||
color: #fbfbfd;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.rn-tag {
|
||||
padding-bottom: calc(11px * var(--rn-s));
|
||||
font-size: calc(12.5px * var(--rn-s));
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: oklch(0.84 0.18 85);
|
||||
}
|
||||
|
||||
.rn-headline {
|
||||
/* CJK breaks anywhere by default; break at phrase boundaries where supported. */
|
||||
word-break: auto-phrase;
|
||||
margin: calc(24px * var(--rn-s)) 0 0;
|
||||
font-size: calc(30px * var(--rn-s));
|
||||
margin: 20px 0 0;
|
||||
font-size: 26px;
|
||||
font-weight: 600;
|
||||
line-height: 1.22;
|
||||
line-height: 1.24;
|
||||
letter-spacing: -0.03em;
|
||||
max-width: calc(600px * var(--rn-s));
|
||||
max-width: 560px;
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
.rn-intro {
|
||||
margin: calc(13px * var(--rn-s)) 0 0;
|
||||
max-width: calc(620px * var(--rn-s));
|
||||
font-size: calc(15.5px * var(--rn-s));
|
||||
line-height: 1.62;
|
||||
margin: 11px 0 0;
|
||||
max-width: 560px;
|
||||
font-size: 16.5px;
|
||||
line-height: 1.6;
|
||||
color: oklch(1 0 0 / 0.62);
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
.rn-features {
|
||||
margin-top: calc(30px * var(--rn-s));
|
||||
.rn-features-head {
|
||||
margin-top: 28px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.rn-features-label { white-space: nowrap; }
|
||||
|
||||
.rn-features-rule { flex: 1; height: 1px; background: oklch(1 0 0 / 0.12); }
|
||||
|
||||
.rn-features-aside {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: oklch(1 0 0 / 0.4);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.rn-features {
|
||||
margin-top: 14px;
|
||||
/* Keeps the foot clear of the cards when the column has no height to spare. */
|
||||
margin-bottom: 26px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.rn-feature {
|
||||
position: relative;
|
||||
display: flex;
|
||||
gap: calc(18px * var(--rn-s));
|
||||
padding: calc(16px * var(--rn-s)) 0;
|
||||
border-top: 1px solid oklch(1 0 0 / 0.09);
|
||||
flex-direction: column;
|
||||
gap: 18px;
|
||||
min-height: 0;
|
||||
padding: 14px 14px 18px;
|
||||
border-radius: 20px;
|
||||
background: linear-gradient(160deg, oklch(1 0 0 / 0.1) 0%, oklch(1 0 0 / 0.045) 62%);
|
||||
border: 1px solid oklch(1 0 0 / 0.13);
|
||||
backdrop-filter: blur(16px) saturate(1.2);
|
||||
-webkit-backdrop-filter: blur(16px) saturate(1.2);
|
||||
box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.16), 0 12px 28px -16px oklch(0 0 0 / 0.7);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.rn-feature:last-child { border-bottom: 1px solid oklch(1 0 0 / 0.09); }
|
||||
|
||||
.rn-feature-icon {
|
||||
width: calc(38px * var(--rn-s));
|
||||
height: calc(38px * var(--rn-s));
|
||||
flex: none;
|
||||
border-radius: calc(12px * var(--rn-s));
|
||||
background: oklch(1 0 0 / 0.07);
|
||||
border: 1px solid oklch(1 0 0 / 0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: oklch(0.9 0.16 88);
|
||||
.rn-feature-shine {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 1px;
|
||||
background: linear-gradient(90deg, transparent, oklch(1 0 0 / 0.4), transparent);
|
||||
}
|
||||
|
||||
.rn-feature-text { min-width: 0; }
|
||||
.rn-feature-visual {
|
||||
position: relative;
|
||||
height: 112px;
|
||||
border-radius: 14px;
|
||||
overflow: hidden;
|
||||
background: oklch(1 0 0 / 0.06);
|
||||
border: 1px solid oklch(1 0 0 / 0.12);
|
||||
}
|
||||
|
||||
.rn-feature-title {
|
||||
font-size: calc(16.5px * var(--rn-s));
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.rn-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-left: calc(4px * var(--rn-s));
|
||||
padding: calc(3px * var(--rn-s)) calc(8px * var(--rn-s));
|
||||
border-radius: calc(6px * var(--rn-s));
|
||||
background: oklch(0.84 0.18 85 / 0.16);
|
||||
border: 1px solid oklch(0.84 0.18 85 / 0.4);
|
||||
font-family: var(--font-subtext);
|
||||
font-size: calc(9.5px * var(--rn-s));
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: oklch(0.9 0.16 88);
|
||||
vertical-align: 2px;
|
||||
line-height: 1.25;
|
||||
letter-spacing: -0.015em;
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
.rn-feature-body {
|
||||
margin-top: calc(5px * var(--rn-s));
|
||||
font-size: calc(14.5px * var(--rn-s));
|
||||
margin-top: 7px;
|
||||
font-size: 13.5px;
|
||||
line-height: 1.55;
|
||||
color: oklch(1 0 0 / 0.58);
|
||||
color: oklch(1 0 0 / 0.6);
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
.rn-release-foot {
|
||||
margin-top: auto;
|
||||
padding-top: calc(28px * var(--rn-s));
|
||||
padding-top: 26px;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: calc(24px * var(--rn-s));
|
||||
flex-wrap: wrap;
|
||||
gap: 20px;
|
||||
border-top: 1px solid oklch(1 0 0 / 0.09);
|
||||
}
|
||||
|
||||
.rn-stats { display: flex; gap: calc(34px * var(--rn-s)); }
|
||||
|
||||
.rn-stat-value {
|
||||
font-family: var(--font-subtext);
|
||||
font-size: calc(20px * var(--rn-s));
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.02em;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.rn-stat-label {
|
||||
margin-top: calc(3px * var(--rn-s));
|
||||
font-size: calc(11px * var(--rn-s));
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
color: oklch(1 0 0 / 0.42);
|
||||
.rn-footnote {
|
||||
font-size: 14.5px;
|
||||
line-height: 1.55;
|
||||
color: oklch(1 0 0 / 0.46);
|
||||
max-width: 360px;
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
.rn-notes {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: calc(12px * var(--rn-s));
|
||||
height: calc(46px * var(--rn-s));
|
||||
padding: 0 calc(8px * var(--rn-s)) 0 calc(20px * var(--rn-s));
|
||||
gap: 11px;
|
||||
height: 44px;
|
||||
padding: 0 7px 0 18px;
|
||||
border-radius: 999px;
|
||||
background: oklch(1 0 0 / 0.07);
|
||||
border: 1px solid oklch(1 0 0 / 0.14);
|
||||
color: #f5f5f7;
|
||||
font-size: calc(14px * var(--rn-s));
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.1);
|
||||
@@ -298,10 +289,10 @@
|
||||
.rn-notes:hover { background: oklch(1 0 0 / 0.12); color: #f5f5f7; }
|
||||
|
||||
.rn-notes-arrow {
|
||||
width: calc(30px * var(--rn-s));
|
||||
height: calc(30px * var(--rn-s));
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
background: oklch(0.9 0.16 88);
|
||||
background: #f5f5f7;
|
||||
color: #101013;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -309,24 +300,192 @@
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.rn-footnote {
|
||||
margin-top: calc(22px * var(--rn-s));
|
||||
padding-top: calc(18px * var(--rn-s));
|
||||
font-size: calc(14px * var(--rn-s));
|
||||
line-height: 1.6;
|
||||
color: oklch(1 0 0 / 0.5);
|
||||
text-wrap: pretty;
|
||||
/* ── The card pictures ─────────────────────────────────────────────────── */
|
||||
|
||||
.rn-vis {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
color: #f5f5f7;
|
||||
font-family: var(--font-system);
|
||||
}
|
||||
|
||||
/*
|
||||
* Its own rule so the footnote only draws a divider when something sits between
|
||||
* it and the feature list. Without the stats row the list's closing border is
|
||||
* already right above it, and two lines land on top of each other.
|
||||
*/
|
||||
.rn-release-foot + .rn-footnote {
|
||||
border-top: 1px solid oklch(1 0 0 / 0.09);
|
||||
.rn-vis-road > svg,
|
||||
.rn-vis-trail > svg { position: absolute; inset: 0; width: 100%; height: 100%; }
|
||||
|
||||
.rn-vis-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: oklch(1 0 0 / 0.55);
|
||||
}
|
||||
|
||||
/* Places API: the index answering a search while it is typed. */
|
||||
.rn-vis-places {
|
||||
padding: 9px 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
/* The same wordmark the API keys card leads with, centred; its pill text inverts against the tile. */
|
||||
.rn-vis-trekbadge { align-self: center; display: flex; align-items: center; height: 24px; }
|
||||
|
||||
.rn-vis-trekmark { display: block; height: 20px; width: auto; color: #f5f5f7; }
|
||||
|
||||
.rn-vis-places .trek-mark .pill-fg { fill: #101013; }
|
||||
|
||||
.rn-vis-search {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
height: 22px;
|
||||
padding: 0 9px;
|
||||
border-radius: 8px;
|
||||
background: oklch(1 0 0 / 0.08);
|
||||
border: 1px solid oklch(1 0 0 / 0.16);
|
||||
font-size: 10px;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.rn-vis-search svg { width: 11px; height: 11px; flex: none; color: oklch(1 0 0 / 0.55); }
|
||||
|
||||
/* The query types itself out once, then the answer arrives under it. */
|
||||
.rn-vis-typed {
|
||||
display: inline-block;
|
||||
max-width: 90px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
animation: rn-type 1.3s steps(13, end) 0.7s both;
|
||||
}
|
||||
|
||||
@keyframes rn-type { from { max-width: 0; } to { max-width: 90px; } }
|
||||
|
||||
.rn-vis-caret {
|
||||
width: 1px;
|
||||
height: 12px;
|
||||
margin-left: -4px;
|
||||
background: #f5f5f7;
|
||||
animation: rn-caret 1s steps(1) infinite;
|
||||
}
|
||||
|
||||
@keyframes rn-caret { 50% { opacity: 0; } }
|
||||
|
||||
.rn-vis-result {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
padding: 5px 8px;
|
||||
border-radius: 8px;
|
||||
background: oklch(1 0 0 / 0.07);
|
||||
animation: rn-answer 0.3s ease 2.1s both;
|
||||
}
|
||||
|
||||
@keyframes rn-answer { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }
|
||||
|
||||
.rn-vis-cat {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
border: 1.5px solid #ffffff;
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.rn-vis-place { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
|
||||
|
||||
.rn-vis-place span {
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.rn-vis-place small { font-size: 8.5px; color: oklch(1 0 0 / 0.5); }
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.rn-vis-typed, .rn-vis-caret, .rn-vis-result { animation: none; }
|
||||
}
|
||||
|
||||
[data-reduce-motion='true'] .rn-vis-typed,
|
||||
[data-reduce-motion='true'] .rn-vis-caret,
|
||||
[data-reduce-motion='true'] .rn-vis-result { animation: none; }
|
||||
|
||||
/* Road trip: the drive on the map, in the planner's route blue and marker style. */
|
||||
.rn-vis-road-casing { fill: none; stroke: #0a5cc2; stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; }
|
||||
|
||||
.rn-vis-road-line { fill: none; stroke: #0a84ff; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
|
||||
|
||||
.rn-vis-marker {
|
||||
position: absolute;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin: -9px 0 0 -9px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid #ffffff;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 1px 4px oklch(0 0 0 / 0.35);
|
||||
color: #ffffff;
|
||||
font-size: 8.5px;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.rn-vis-distance {
|
||||
position: absolute;
|
||||
right: 9px;
|
||||
bottom: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 2px 7px;
|
||||
border-radius: 99px;
|
||||
background: #f5f5f7;
|
||||
color: #101013;
|
||||
font-size: 9px;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
/* Dawarich: a recorded day, in the trail colour the map draws it with. */
|
||||
.rn-vis-trail-line { fill: none; stroke: #2563eb; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
|
||||
|
||||
.rn-vis-trail-stay { fill: #ffffff; stroke: #2563eb; stroke-width: 2; }
|
||||
|
||||
/* The mark itself, unframed, with its corners rounded like an app icon. */
|
||||
.rn-vis-brand {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
left: 12px;
|
||||
width: 58px;
|
||||
height: 58px;
|
||||
border-radius: 15px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 14px oklch(0 0 0 / 0.45), 0 0 0 1px oklch(1 0 0 / 0.14);
|
||||
}
|
||||
|
||||
/* A glass sheen over the mark: a soft light from the top and a bright inner edge. */
|
||||
.rn-vis-brand::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
background: linear-gradient(160deg, oklch(1 0 0 / 0.42) 0%, oklch(1 0 0 / 0.08) 38%, transparent 55%, oklch(0 0 0 / 0.12) 100%);
|
||||
box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.55), inset 0 0 0 1px oklch(1 0 0 / 0.22);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.rn-vis-brand img { display: block; width: 100%; height: 100%; }
|
||||
|
||||
/* ── Right: the note ───────────────────────────────────────────────────── */
|
||||
|
||||
.rn-note {
|
||||
@@ -340,10 +499,10 @@
|
||||
|
||||
.rn-close {
|
||||
position: absolute;
|
||||
top: calc(24px * var(--rn-s));
|
||||
right: calc(24px * var(--rn-s));
|
||||
width: calc(38px * var(--rn-s));
|
||||
height: calc(38px * var(--rn-s));
|
||||
top: 22px;
|
||||
right: 22px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
background: var(--bg-hover);
|
||||
border: 1px solid var(--border-faint);
|
||||
@@ -361,15 +520,19 @@
|
||||
.rn-note-body {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
padding: calc(50px * var(--rn-s)) calc(52px * var(--rn-s)) calc(30px * var(--rn-s));
|
||||
padding: 44px 44px 26px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.rn-note-body::-webkit-scrollbar { display: none; }
|
||||
|
||||
.rn-note-eyebrow {
|
||||
font-family: var(--font-subtext);
|
||||
font-size: calc(11.5px * var(--rn-s));
|
||||
font-size: 11px;
|
||||
line-height: 14px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.2em;
|
||||
text-transform: uppercase;
|
||||
@@ -377,103 +540,139 @@
|
||||
}
|
||||
|
||||
.rn-note-title {
|
||||
/* CJK breaks anywhere by default; break at phrase boundaries where supported. */
|
||||
word-break: auto-phrase;
|
||||
margin: calc(16px * var(--rn-s)) 0 0;
|
||||
font-size: calc(29px * var(--rn-s));
|
||||
margin: 14px 0 0;
|
||||
font-size: 29px;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
letter-spacing: -0.03em;
|
||||
max-width: calc(420px * var(--rn-s));
|
||||
max-width: 420px;
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
.rn-note p {
|
||||
margin: calc(20px * var(--rn-s)) 0 0;
|
||||
font-size: calc(15px * var(--rn-s));
|
||||
line-height: 1.68;
|
||||
margin: 20px 0 0;
|
||||
font-size: 16px;
|
||||
line-height: 1.66;
|
||||
color: var(--text-secondary);
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
.rn-note p + p { margin-top: calc(15px * var(--rn-s)); }
|
||||
.rn-note p + p { margin-top: 14px; }
|
||||
|
||||
/*
|
||||
* The promise is a pane of glass in the inverse of the note: dark on a light note,
|
||||
* light on a dark one, with the same sheen and edge light as the release cards.
|
||||
*/
|
||||
.rn-promise {
|
||||
margin-top: calc(24px * var(--rn-s));
|
||||
padding: calc(20px * var(--rn-s)) calc(22px * var(--rn-s));
|
||||
border-radius: calc(20px * var(--rn-s));
|
||||
background: oklch(0.72 0.11 190 / 0.1);
|
||||
border: 1px solid oklch(0.72 0.11 190 / 0.28);
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
overflow: hidden;
|
||||
margin-top: 24px;
|
||||
padding: 18px 20px;
|
||||
border-radius: 18px;
|
||||
background: linear-gradient(
|
||||
160deg,
|
||||
color-mix(in oklch, var(--text-primary) 94%, transparent) 0%,
|
||||
color-mix(in oklch, var(--text-primary) 80%, transparent) 100%
|
||||
);
|
||||
border: 1px solid color-mix(in oklch, var(--text-primary) 55%, transparent);
|
||||
backdrop-filter: blur(16px) saturate(1.3);
|
||||
-webkit-backdrop-filter: blur(16px) saturate(1.3);
|
||||
box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.2), 0 16px 34px -20px oklch(0 0 0 / 0.6);
|
||||
color: var(--bg-primary);
|
||||
}
|
||||
|
||||
/* The edge light along the top, as on the cards. */
|
||||
.rn-promise::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 1px;
|
||||
background: linear-gradient(90deg, transparent, oklch(1 0 0 / 0.5), transparent);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* A soft light falling in from the top left, and a faint glow where it leaves. */
|
||||
.rn-promise::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background:
|
||||
radial-gradient(120% 110% at 0% 0%, oklch(1 0 0 / 0.16) 0%, transparent 55%),
|
||||
radial-gradient(80% 90% at 100% 100%, oklch(0.84 0.18 85 / 0.12) 0%, transparent 60%);
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.rn-promise-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: calc(9px * var(--rn-s));
|
||||
gap: 9px;
|
||||
font-family: var(--font-subtext);
|
||||
font-size: calc(11px * var(--rn-s));
|
||||
font-size: 10.5px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.16em;
|
||||
text-transform: uppercase;
|
||||
color: oklch(0.55 0.09 190);
|
||||
color: color-mix(in oklch, var(--bg-primary) 55%, transparent);
|
||||
}
|
||||
|
||||
.dark .rn-promise-label { color: oklch(0.78 0.1 190); }
|
||||
|
||||
.rn-promise-text {
|
||||
margin-top: calc(10px * var(--rn-s));
|
||||
font-size: calc(15.5px * var(--rn-s));
|
||||
font-weight: 600;
|
||||
line-height: 1.55;
|
||||
margin-top: 9px;
|
||||
font-size: 16.5px;
|
||||
line-height: 1.5;
|
||||
letter-spacing: -0.01em;
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
.rn-signoff { margin-top: auto; padding-top: calc(26px * var(--rn-s)); }
|
||||
.rn-promise-text b { font-weight: 600; }
|
||||
|
||||
.rn-promise-text span { font-weight: 400; color: color-mix(in oklch, var(--bg-primary) 68%, transparent); }
|
||||
|
||||
.rn-closing {
|
||||
font-size: calc(18px * var(--rn-s));
|
||||
margin-top: auto;
|
||||
padding-top: 24px;
|
||||
font-size: 16.5px;
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.02em;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.rn-signature {
|
||||
margin-top: calc(8px * var(--rn-s));
|
||||
font-size: calc(15px * var(--rn-s));
|
||||
font-weight: 500;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.rn-support {
|
||||
padding: calc(26px * var(--rn-s)) calc(52px * var(--rn-s)) calc(34px * var(--rn-s));
|
||||
padding: 22px 44px 26px;
|
||||
border-top: 1px solid var(--border-primary);
|
||||
background: var(--bg-secondary);
|
||||
background: var(--bg-hover);
|
||||
}
|
||||
|
||||
.rn-support-text {
|
||||
font-size: calc(15px * var(--rn-s));
|
||||
line-height: 1.68;
|
||||
font-size: 15.5px;
|
||||
line-height: 1.62;
|
||||
color: var(--text-secondary);
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
.rn-support-text b { font-weight: 600; color: var(--text-primary); }
|
||||
|
||||
.rn-support-buttons {
|
||||
margin-top: calc(16px * var(--rn-s));
|
||||
margin-top: 14px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: calc(10px * var(--rn-s));
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.rn-support-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: calc(9px * var(--rn-s));
|
||||
height: calc(50px * var(--rn-s));
|
||||
border-radius: calc(16px * var(--rn-s));
|
||||
font-size: calc(14.5px * var(--rn-s));
|
||||
gap: 9px;
|
||||
height: 50px;
|
||||
border-radius: 15px;
|
||||
font-size: 15.5px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
box-shadow: 0 2px 6px oklch(0 0 0 / 0.1);
|
||||
cursor: pointer;
|
||||
border: 0;
|
||||
@@ -482,19 +681,41 @@
|
||||
|
||||
.rn-support-btn:hover { filter: brightness(0.96); }
|
||||
|
||||
/* Brand colours — theme-lint-disable: Buy Me a Coffee and Ko-fi own these. */
|
||||
.rn-support-bmc { background: #ffdd00; color: #101013; }
|
||||
.rn-support-kofi { background: #ff5e5b; color: #ffffff; }
|
||||
/* The steam lifts off the cup in turn, and the heart beats. */
|
||||
.rn-coffee { overflow: visible; }
|
||||
.rn-steam { stroke-width: 1.8; animation: rn-steam 3s ease-in-out infinite; }
|
||||
.rn-steam:nth-of-type(4) { animation-delay: 0.5s; }
|
||||
.rn-steam:nth-of-type(5) { animation-delay: 1s; }
|
||||
|
||||
@keyframes rn-steam {
|
||||
0% { opacity: 0; transform: translate(0, 3px); }
|
||||
25% { opacity: 1; transform: translate(-0.7px, -1px); }
|
||||
55% { opacity: 0.85; transform: translate(0.7px, -5px); }
|
||||
100% { opacity: 0; transform: translate(-0.4px, -10px); }
|
||||
}
|
||||
|
||||
.rn-heart { transform-origin: 50% 55%; animation: rn-beat 1.3s ease-in-out infinite; }
|
||||
|
||||
@keyframes rn-beat {
|
||||
0%, 60%, 100% { transform: scale(1); }
|
||||
15% { transform: scale(1.2); }
|
||||
30% { transform: scale(1); }
|
||||
45% { transform: scale(1.12); }
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.rn-steam, .rn-heart { animation: none; }
|
||||
}
|
||||
|
||||
[data-reduce-motion='true'] .rn-steam,
|
||||
[data-reduce-motion='true'] .rn-heart { animation: none; }
|
||||
|
||||
/* Brand colours: Buy Me a Coffee and Ko-fi own these. */
|
||||
.rn-support-bmc { background: #ffdd00; color: #101013; } /* theme-lint-disable */
|
||||
.rn-support-kofi { background: #ff5e5b; color: #ffffff; } /* theme-lint-disable */
|
||||
|
||||
/* Narrow viewports: keep the proportions, drop the outer padding. */
|
||||
@media (max-width: 900px) {
|
||||
.rn-overlay { padding: 0; }
|
||||
.rn-panel { border-radius: 0; border: 0; max-height: 100%; }
|
||||
}
|
||||
|
||||
/* Icons carry fixed size attributes from lucide; scale them with the panel. */
|
||||
.rn-feature-icon svg { width: calc(18px * var(--rn-s)); height: calc(18px * var(--rn-s)); }
|
||||
.rn-notes-arrow svg { width: calc(16px * var(--rn-s)); height: calc(16px * var(--rn-s)); }
|
||||
.rn-promise-label svg { width: calc(14px * var(--rn-s)); height: calc(14px * var(--rn-s)); flex: none; }
|
||||
.rn-support-btn svg { width: calc(18px * var(--rn-s)); height: calc(18px * var(--rn-s)); flex: none; }
|
||||
.rn-close svg { width: calc(18px * var(--rn-s)); height: calc(18px * var(--rn-s)); }
|
||||
|
||||
@@ -31,92 +31,88 @@ export const RETIRED_NOTICE_IDS = [
|
||||
'v3-mcp',
|
||||
'v3-features',
|
||||
'welcome-v1',
|
||||
'release-4-0-0',
|
||||
] as const;
|
||||
|
||||
export const SYSTEM_NOTICES: SystemNotice[] = [
|
||||
// ── 4.0.0 release — what shipped, and a note from the maintainer ────────────
|
||||
// Carries `release`, so it renders as the two-column release modal rather than
|
||||
// the generic notice body. 4.0.0 was big enough that the whole 4.x line should
|
||||
// carry it, so `recurring: 'per-version'` brings it back on each upgrade inside
|
||||
// the window rather than the default one-time dismissal, which retired it for
|
||||
// everyone who closed it once on 4.0.0. A 5.x release gets its own entry.
|
||||
// ── Release notes: what the current release brought, and a note from the maintainer ──
|
||||
// One entry for every release. Each big release swaps the copy (the release_notes
|
||||
// keys) and the version below, and keeps this id. `recurring: 'per-version'` brings
|
||||
// it back to every user on every upgrade, a patch release included, so nobody is
|
||||
// ever left on a version with nothing to show. No upper bound for the same reason.
|
||||
{
|
||||
id: 'release-4-0-0',
|
||||
id: 'release-notes',
|
||||
recurring: 'per-version',
|
||||
display: 'modal',
|
||||
severity: 'info',
|
||||
titleKey: 'system_notice.release_400.headline',
|
||||
bodyKey: 'system_notice.release_400.intro',
|
||||
titleKey: 'system_notice.release_notes.headline',
|
||||
bodyKey: 'system_notice.release_notes.intro',
|
||||
release: {
|
||||
version: '4.0.0',
|
||||
eyebrowKey: 'system_notice.release_400.eyebrow',
|
||||
tagKey: 'system_notice.release_400.tag',
|
||||
headlineKey: 'system_notice.release_400.headline',
|
||||
introKey: 'system_notice.release_400.intro',
|
||||
version: '4.3.0',
|
||||
eyebrowKey: 'system_notice.release_notes.eyebrow',
|
||||
headlineKey: 'system_notice.release_notes.headline',
|
||||
introKey: 'system_notice.release_notes.intro',
|
||||
featuresLabelKey: 'system_notice.release_notes.features_label',
|
||||
featuresAsideKey: 'system_notice.release_notes.features_aside',
|
||||
features: [
|
||||
{
|
||||
iconName: 'Smartphone',
|
||||
titleKey: 'system_notice.release_400.feature_mobile_title',
|
||||
bodyKey: 'system_notice.release_400.feature_mobile_body',
|
||||
iconName: 'Database',
|
||||
visual: 'places-api',
|
||||
titleKey: 'system_notice.release_notes.feature_places_title',
|
||||
bodyKey: 'system_notice.release_notes.feature_places_body',
|
||||
},
|
||||
{
|
||||
iconName: 'BookOpen',
|
||||
titleKey: 'system_notice.release_400.feature_studio_title',
|
||||
bodyKey: 'system_notice.release_400.feature_studio_body',
|
||||
badgeKey: 'system_notice.release_400.feature_studio_badge',
|
||||
iconName: 'Route',
|
||||
visual: 'roadtrip',
|
||||
titleKey: 'system_notice.release_notes.feature_roadtrip_title',
|
||||
bodyKey: 'system_notice.release_notes.feature_roadtrip_body',
|
||||
},
|
||||
{
|
||||
iconName: 'CalendarDays',
|
||||
titleKey: 'system_notice.release_400.feature_vacay_title',
|
||||
bodyKey: 'system_notice.release_400.feature_vacay_body',
|
||||
},
|
||||
{
|
||||
iconName: 'Image',
|
||||
titleKey: 'system_notice.release_400.feature_places_title',
|
||||
bodyKey: 'system_notice.release_400.feature_places_body',
|
||||
iconName: 'MapPin',
|
||||
visual: 'dawarich',
|
||||
titleKey: 'system_notice.release_notes.feature_dawarich_title',
|
||||
bodyKey: 'system_notice.release_notes.feature_dawarich_body',
|
||||
},
|
||||
],
|
||||
// No stat row and no notes button here: the left column reads better short.
|
||||
footnoteKey: 'system_notice.release_400.footnote',
|
||||
note: {
|
||||
eyebrowKey: 'system_notice.release_400.note_eyebrow',
|
||||
titleKey: 'system_notice.release_400.note_title',
|
||||
bodyKey: 'system_notice.release_400.note_body',
|
||||
promiseLabelKey: 'system_notice.release_400.promise_label',
|
||||
promiseTextKey: 'system_notice.release_400.promise_text',
|
||||
bodyAfterKey: 'system_notice.release_400.note_body_after',
|
||||
closingKey: 'system_notice.release_400.note_closing',
|
||||
signatureKey: 'system_notice.release_400.note_signature',
|
||||
footnoteKey: 'system_notice.release_notes.footnote',
|
||||
notes: {
|
||||
labelKey: 'system_notice.release_notes.notes_label',
|
||||
href: 'https://github.com/liketrek/TREK/releases/tag/v4.3.0',
|
||||
},
|
||||
supportTextKey: 'system_notice.release_400.support_text',
|
||||
note: {
|
||||
eyebrowKey: 'system_notice.release_notes.note_eyebrow',
|
||||
titleKey: 'system_notice.release_notes.note_title',
|
||||
bodyKey: 'system_notice.release_notes.note_body',
|
||||
promiseLabelKey: 'system_notice.release_notes.promise_label',
|
||||
promiseLeadKey: 'system_notice.release_notes.promise_lead',
|
||||
promiseTextKey: 'system_notice.release_notes.promise_text',
|
||||
bodyAfterKey: 'system_notice.release_notes.note_body_after',
|
||||
closingKey: 'system_notice.release_notes.note_closing',
|
||||
},
|
||||
supportLeadKey: 'system_notice.release_notes.support_lead',
|
||||
supportTextKey: 'system_notice.release_notes.support_text',
|
||||
},
|
||||
cta: {
|
||||
kind: 'link',
|
||||
labelKey: 'system_notice.release_400.cta_bmc',
|
||||
labelKey: 'system_notice.release_notes.cta_bmc',
|
||||
href: 'https://buymeacoffee.com/mauriceboe',
|
||||
},
|
||||
secondaryCta: {
|
||||
kind: 'link',
|
||||
labelKey: 'system_notice.release_400.cta_kofi',
|
||||
labelKey: 'system_notice.release_notes.cta_kofi',
|
||||
href: 'https://ko-fi.com/mauriceboe',
|
||||
},
|
||||
dismissible: true,
|
||||
// Desktop-only, like the thank-you modal it replaces: the two-column layout
|
||||
// has no phone form, and the mobile release lands with its own onboarding.
|
||||
// Desktop-only: the two-column layout has no phone form, and the phone has its
|
||||
// own onboarding.
|
||||
desktopOnly: true,
|
||||
// Same reasoning as the thank-you notice below: it asks the reader to fund
|
||||
// the project, and on a managed install they already pay whoever runs it.
|
||||
// It asks the reader to fund the project, and on a managed install they already
|
||||
// pay whoever runs it.
|
||||
conditions: [{ kind: 'managed', is: false }],
|
||||
publishedAt: '2026-08-22T00:00:00Z',
|
||||
publishedAt: '2026-09-15T00:00:00Z',
|
||||
priority: 110,
|
||||
// The whole 4.x line. The copy is about what 4.0.0 brought, and that is still
|
||||
// what somebody arriving anywhere on 4.x is being introduced to — the minor
|
||||
// releases after it add to that picture rather than replace it. Held open to
|
||||
// the 5.0.0 boundary (exclusive) so a 4.1/4.2 install is not left with no
|
||||
// notice at all, which is what a per-release window did the moment 4.1.0
|
||||
// shipped without an entry of its own.
|
||||
// Where the thank-you notice below hands over; nothing on 3.x ships this copy.
|
||||
minVersion: '4.0.0',
|
||||
maxVersion: '5.0.0',
|
||||
},
|
||||
|
||||
// ── Thank-you + support the project — shown once per install AND once per upgrade ──
|
||||
|
||||
@@ -30,15 +30,10 @@ export type NoticeCta =
|
||||
|
||||
export interface NoticeReleaseFeature {
|
||||
iconName: string;
|
||||
/** A small illustration the client draws on the card; unknown names fall back to the icon. */
|
||||
visual?: string;
|
||||
titleKey: string;
|
||||
bodyKey: string;
|
||||
badgeKey?: string;
|
||||
}
|
||||
|
||||
export interface NoticeReleaseStat {
|
||||
/** The figure itself ("~150") — shown as-is, never translated. */
|
||||
value: string;
|
||||
labelKey: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,11 +44,11 @@ export interface NoticeReleaseStat {
|
||||
export interface NoticeRelease {
|
||||
version: string;
|
||||
eyebrowKey: string;
|
||||
tagKey: string;
|
||||
headlineKey: string;
|
||||
introKey: string;
|
||||
featuresLabelKey: string;
|
||||
featuresAsideKey?: string;
|
||||
features: NoticeReleaseFeature[];
|
||||
stats?: NoticeReleaseStat[];
|
||||
notes?: { labelKey: string; href: string };
|
||||
footnoteKey?: string;
|
||||
note: {
|
||||
@@ -61,11 +56,12 @@ export interface NoticeRelease {
|
||||
titleKey: string;
|
||||
bodyKey: string;
|
||||
promiseLabelKey: string;
|
||||
promiseLeadKey: string;
|
||||
promiseTextKey: string;
|
||||
bodyAfterKey: string;
|
||||
closingKey: string;
|
||||
signatureKey: string;
|
||||
};
|
||||
supportLeadKey: string;
|
||||
supportTextKey: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ describe('GET /api/system-notices/active', () => {
|
||||
// login_count > 1 means firstLogin does not match; first_seen_version >= 3.0.0 means
|
||||
// existingUserBeforeVersion('3.0.0') does not match either. Notices that gate on
|
||||
// nothing but the install being self-hosted still apply, and which ones those are
|
||||
// changes every release — the thank-you modal handed over to release-4-0-0 at 4.0.0.
|
||||
// changes every release (the thank-you modal handed over to the release notes at 4.0.0).
|
||||
// Read the set out of the registry rather than naming them, or this ages out again.
|
||||
testDb.prepare('UPDATE users SET login_count = 5, first_seen_version = ? WHERE id = ?').run('3.0.0', user.id);
|
||||
const alwaysOn = new Set(
|
||||
@@ -226,6 +226,47 @@ describe('GET /api/system-notices/active', () => {
|
||||
if (idx !== -1) SYSTEM_NOTICES.splice(idx, 1);
|
||||
}
|
||||
});
|
||||
|
||||
// The release notes carry the support links, so the promise is exact: once per
|
||||
// update for every user, whatever they did with it before, and never again on a
|
||||
// reload of the same version. Driven through the real registry entry and the real
|
||||
// dismiss route, so neither half can drift away from the other unnoticed.
|
||||
it('shows the release notes once per update, however often they were closed before', async () => {
|
||||
const { user } = createUser(testDb);
|
||||
testDb.prepare('UPDATE users SET login_count = 5, first_seen_version = ? WHERE id = ?').run('3.0.0', user.id);
|
||||
|
||||
const shows = async () => {
|
||||
const res = await request(app)
|
||||
.get('/api/system-notices/active')
|
||||
.set('Cookie', authCookie(user.id));
|
||||
expect(res.status).toBe(200);
|
||||
return res.body.some((n: { id: string }) => n.id === 'release-notes');
|
||||
};
|
||||
const dismiss = async () => {
|
||||
const res = await request(app)
|
||||
.post('/api/system-notices/release-notes/dismiss')
|
||||
.set('Cookie', authCookie(user.id));
|
||||
expect(res.status).toBe(204);
|
||||
};
|
||||
|
||||
expect(await shows()).toBe(true);
|
||||
|
||||
// Closed on this version: gone for every reload after it.
|
||||
await dismiss();
|
||||
expect(await shows()).toBe(false);
|
||||
expect(await shows()).toBe(false);
|
||||
|
||||
// The next update brings it back, although it was closed before...
|
||||
testDb.prepare(
|
||||
'UPDATE user_notice_dismissals SET dismissed_app_version = ? WHERE user_id = ? AND notice_id = ?'
|
||||
).run('4.0.0', user.id, 'release-notes');
|
||||
expect(await shows()).toBe(true);
|
||||
expect(await shows()).toBe(true);
|
||||
|
||||
// ...and closing it again holds until the one after that.
|
||||
await dismiss();
|
||||
expect(await shows()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -2,7 +2,7 @@ import { describe, it, expect } from 'vitest';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import semver from 'semver';
|
||||
import { SYSTEM_NOTICES } from '../../../src/systemNotices/registry.js';
|
||||
import { RETIRED_NOTICE_IDS, SYSTEM_NOTICES } from '../../../src/systemNotices/registry.js';
|
||||
import { isNoticeVersionActive } from '../../../src/systemNotices/service.js';
|
||||
|
||||
/** Collect all actionIds registered via registerNoticeAction() in client source files. */
|
||||
@@ -65,29 +65,28 @@ describe('registry integrity', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('the 4.0.0 release notice covers the whole 4.x line', () => {
|
||||
const release = SYSTEM_NOTICES.find(n => n.id === 'release-4-0-0');
|
||||
it('the release notes come back on every upgrade, with no upper bound', () => {
|
||||
const release = SYSTEM_NOTICES.find(n => n.id === 'release-notes');
|
||||
expect(release).toBeDefined();
|
||||
// It must not greet somebody still on 3.x...
|
||||
// Nothing on 3.x ships this copy, and the thank-you notice still covers it there.
|
||||
expect(isNoticeVersionActive(release!, '3.4.1')).toBe(false);
|
||||
expect(isNoticeVersionActive(release!, '4.0.0')).toBe(true);
|
||||
expect(isNoticeVersionActive(release!, '4.0.7')).toBe(true);
|
||||
expect(isNoticeVersionActive(release!, '4.0.12')).toBe(true);
|
||||
// ...and it stays up across the minors, so no 4.x install is left without a
|
||||
// notice the way 4.1.0 was under the old per-release window.
|
||||
expect(isNoticeVersionActive(release!, '4.1.0')).toBe(true);
|
||||
expect(isNoticeVersionActive(release!, '4.2.0')).toBe(true);
|
||||
expect(isNoticeVersionActive(release!, '4.9.9')).toBe(true);
|
||||
// The upper bound is exclusive: 5.0.0 gets its own notice.
|
||||
expect(isNoticeVersionActive(release!, '5.0.0')).toBe(false);
|
||||
// From there on every version carries it, a patch release included, so no
|
||||
// install is left with nothing to show because nobody wrote a new window.
|
||||
for (const version of ['4.0.0', '4.2.1', '4.3.0', '4.3.1', '4.9.9', '5.0.0', '12.4.0']) {
|
||||
expect(isNoticeVersionActive(release!, version), version).toBe(true);
|
||||
}
|
||||
expect(release!.maxVersion).toBeUndefined();
|
||||
// The window alone is not enough: a one-time dismissal would retire it for good
|
||||
// the first time somebody closed it.
|
||||
expect(release!.recurring).toBe('per-version');
|
||||
});
|
||||
|
||||
it('the 4.0.0 release notice comes back on each upgrade inside that line', () => {
|
||||
const release = SYSTEM_NOTICES.find(n => n.id === 'release-4-0-0')!;
|
||||
// The version window above is only half of "covers the whole 4.x line". Without
|
||||
// this, the default one-time dismissal retired the notice for everyone who
|
||||
// closed it on 4.0.0, so none of them saw it again on 4.1, 4.2 or later.
|
||||
expect(release.recurring).toBe('per-version');
|
||||
it('the 4.0.0 release notice is retired and its id stays reserved', () => {
|
||||
expect(SYSTEM_NOTICES.some(n => n.id === 'release-4-0-0')).toBe(false);
|
||||
expect(RETIRED_NOTICE_IDS).toContain('release-4-0-0');
|
||||
for (const id of RETIRED_NOTICE_IDS) {
|
||||
expect(SYSTEM_NOTICES.some(n => n.id === id), id).toBe(false);
|
||||
}
|
||||
});
|
||||
|
||||
it('the thank-you notice hands over to the release modal at 4.0.0', () => {
|
||||
@@ -98,10 +97,10 @@ describe('registry integrity', () => {
|
||||
expect(isNoticeVersionActive(thankYou!, '3.4.1')).toBe(true);
|
||||
expect(isNoticeVersionActive(thankYou!, '4.0.0')).toBe(false);
|
||||
|
||||
const release = SYSTEM_NOTICES.find(n => n.id === 'release-4-0-0')!;
|
||||
for (const version of ['3.4.1', '4.0.0', '4.0.7', '4.1.0', '5.0.0']) {
|
||||
const release = SYSTEM_NOTICES.find(n => n.id === 'release-notes')!;
|
||||
for (const version of ['3.4.1', '4.0.0', '4.0.7', '4.1.0', '4.3.0', '5.0.0']) {
|
||||
const active = [thankYou!, release].filter(n => isNoticeVersionActive(n, version));
|
||||
expect(active.length, `both thank-you notices active at ${version}`).toBeLessThanOrEqual(1);
|
||||
expect(active.length, `thank-you and release notes at ${version}`).toBe(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -35,6 +35,12 @@ export const ALLOWED = [
|
||||
'settings.about.descriptionManaged instead, so neither reader is told the ' +
|
||||
'wrong thing and self-hosters lose nothing.',
|
||||
},
|
||||
{
|
||||
key: 'system_notice.release_notes.feature_dawarich_body',
|
||||
because:
|
||||
'it calls Dawarich self-hosted, not TREK, which is what Dawarich is, and the ' +
|
||||
'release notice carrying it is shown only where the managed condition is false',
|
||||
},
|
||||
{
|
||||
key: 'system_notice.v3_thankyou.body',
|
||||
because:
|
||||
|
||||
@@ -53,40 +53,38 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.thank_you_support.cta_bmc': 'Buy Me a Coffee',
|
||||
'system_notice.thank_you_support.cta_kofi': 'ادعمني على Ko-fi',
|
||||
'system_notice.pager.counter': '{current} / {total}', // en-fallback
|
||||
'system_notice.release_400.eyebrow': 'تم تثبيت التحديث',
|
||||
'system_notice.release_400.tag': 'إصدار',
|
||||
'system_notice.release_400.headline': 'أكبر إصدار حظي به TREK على الإطلاق.',
|
||||
'system_notice.release_400.intro':
|
||||
'يحصل TREK على هاتف، وعلى كتاب. تسعة عشر شخصًا كتبوا هذا الإصدار — ومعه نحو مئة وخمسين بلاغ خطأ تم إصلاحها.',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK على الهاتف',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'كل ما دون 768px صار واجهة مستقلة — شريط زجاجي، ولوحات منزلقة خاصة به، ومخطط رحلة خاص به. افتح TREK على هاتفك.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'تحوّل PDF الخاص بـ Journey إلى مصمّم ألبومات صور. يرتّب الألبوم حين تطلب منه، ثم يبتعد عن طريقك.',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay يتعلّم الباقي',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'أنصاف الأيام، وأيام التعويض والمرونة، والعطل المدرسية على الشبكة — وسنة إجازات لا يلزم أن تبدأ في يناير.',
|
||||
'system_notice.release_400.feature_places_title': 'الأماكن تعرّف عن نفسها، والملفات تنتقل',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'تُملأ الصور والوصف تلقائيًا قبل أن تحفظ المكان. ولم تعد ملفاتك المرفوعة مضطرة للبقاء على القرص الذي يعمل عليه TREK.',
|
||||
'system_notice.release_400.footnote':
|
||||
'وهذه أربعة منها فقط. يحمل 4.0.0 مئات التغييرات الأخرى، من Collections و Atlas إلى الخادم بأكمله تحتها.',
|
||||
'system_notice.release_400.note_eyebrow': 'كلمة من صاحب المشروع',
|
||||
'system_notice.release_400.note_title': 'شكرًا لاستخدامك TREK.',
|
||||
'system_notice.release_400.note_body':
|
||||
'بدأ TREK كأداة صغيرة لرحلاتي الخاصة، كتبتها في وقت فراغي. وما زال كذلك: أمسيات، وعطل نهاية الأسبوع، والساعات المتبقية بجانب عمل بدوام كامل.\n\nلفترة كنت وحدي. لم يعد الأمر كذلك — تسعة عشر شخصًا أطلقوا هذا الإصدار، وآلاف منكم جاؤوا بنجوم ومشكلات وترجمات وطلبات دمج. أنا ممتن لكل جزء من ذلك.',
|
||||
'system_notice.release_400.promise_label': 'الوعد',
|
||||
'system_notice.release_400.promise_text':
|
||||
'الجانب مفتوح المصدر من TREK يبقى مجانيًا، إلى الأبد. لا باقات مدفوعة، لا اشتراكات، لا شروط خفية. أعدكم.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'استغرق 4.0.0 أسابيع من الليالي المتأخرة — تطبيق هاتف، ومصمّم ألبومات، وترحيل الخادم، معظمه كُتب بين منتصف الليل والثانية. ليست شكوى: أحب بناء هذا. إنها فقط الإجابة الصادقة عن كيف يخرج إصدار بهذا الحجم من مشروع في وقت الفراغ.',
|
||||
'system_notice.release_400.note_closing': 'شكرًا لوجودك هنا.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'الدعم هو ما يبقي هذا مستمرًا — الخوادم والنطاقات والليالي المتأخرة التي تتحول إلى إصدارات كهذا. إذا كان TREK يساوي شيئًا لك، ففنجان قهوة هو أقصر طريق لإبقائه مستمرًا.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'ادعمني على Ko-fi',
|
||||
'system_notice.release_notes.eyebrow': 'تم تثبيت التحديث',
|
||||
'system_notice.release_notes.headline': 'ثلاثة أشياء صار TREK يتولاها بنفسه.',
|
||||
'system_notice.release_notes.intro':
|
||||
'واجهة API خاصة به للأماكن، ورحلات برية مخطَّطة من أولها إلى آخرها، وسجل مواقعك يعود إلى يديك.',
|
||||
'system_notice.release_notes.features_label': 'أبرز الجديد',
|
||||
'system_notice.release_notes.features_aside': 'وهذا ليس كل شيء',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'أول مخطط سفر مفتوح المصدر يستضيف واجهة API خاصة به للأماكن. 73.6 مليون مكان، يُعاد بناؤها كل شهر. بلا مفتاح ولا حصة.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'إضافة الرحلة البرية',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'وضع الرحلة البرية يخطط القيادة نفسها: المسار، ومسافته، وساعات القيادة، ومحطات التوقف. إنها إضافة، تبقى معطَّلة حتى يفعّلها المسؤول.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'تكامل Dawarich',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'البديل المستضاف ذاتيًا لـ Google Timeline، وصار بالإمكان الآن قراءته داخل TREK. يقرأ TREK، ويقرأ فقط. ولا يُكتب فيه أي شيء أبدًا.',
|
||||
'system_notice.release_notes.footnote': 'إلى جانب قائمة طويلة من التغييرات الأصغر في بقية أرجاء TREK.',
|
||||
'system_notice.release_notes.notes_label': 'ملاحظات الإصدار',
|
||||
'system_notice.release_notes.note_eyebrow': 'كلمة من صاحب المشروع',
|
||||
'system_notice.release_notes.note_title': 'أنتم السبب في أنني ما زلت أبني TREK.',
|
||||
'system_notice.release_notes.note_body':
|
||||
'بدأ TREK كأداة صغيرة لرحلاتي الخاصة، كتبتها بعد العمل لأنني أردت طريقة أفضل لتخطيطها. ومنذ ذلك الحين لم يتوقف عن النمو. كل ما تستخدمه تقريبًا بُني في ساعات متأخرة من الليل، وفي عطل نهاية الأسبوع، وفي القطارات، إلى جانب عمل بدوام كامل، وكم من أمسية تساءلت فيها بيني وبين نفسي: هل سيفتحه أحد يومًا؟',
|
||||
'system_notice.release_notes.promise_label': 'الوعد',
|
||||
'system_notice.release_notes.promise_lead': 'سيبقى TREK مجانيًا، إلى الأبد.',
|
||||
'system_notice.release_notes.promise_text': 'كل ميزة، وكل تحديث، للجميع. لا باقات مدفوعة، لا اشتراكات، لا شروط خفية.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'ثم فتحتموه. وخلال بضعة أشهر صرتم بالآلاف: نجوم، وبلاغات أخطاء، وترجمات إلى لغات لا أتحدثها، وطلبات دمج من أشخاص لم ألتقِ بهم قط. ما زلت أتفقد المستودع أول شيء كل صباح، وما زال الأمر لا يبدو حقيقيًا تمامًا.',
|
||||
'system_notice.release_notes.note_closing': 'شكرًا لوجودك هنا. مع تحياتي، Maurice.',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'صحيح أن TREK مجاني وسيبقى كذلك دائمًا، لكن الخوادم والنطاقات والكثير من الليالي المتأخرة ليست مجانية.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'إن كان TREK قد استحق مكانًا في رحلاتك، فاشترِ لي فنجان قهوة وساعد في أن يرى الإصدار القادم النور.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'ادعمني على Ko-fi',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -54,41 +54,40 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.v3014_whitespace_collision.title': 'Ação necessária: conflito de conta de usuário',
|
||||
'system_notice.v3014_whitespace_collision.body':
|
||||
'A atualização 3.0.14 detectou um ou mais conflitos de nome de usuário ou e-mail causados por espaços em branco no início ou fim dos valores armazenados. As contas afetadas foram renomeadas automaticamente. Verifique os logs do servidor por linhas começando com **[migration] WHITESPACE COLLISION** para identificar quais contas precisam de revisão.',
|
||||
// 4.0.0 release modal — the release on the left, the note from the maintainer on the right
|
||||
'system_notice.release_400.eyebrow': 'Atualização instalada',
|
||||
'system_notice.release_400.tag': 'Versão',
|
||||
'system_notice.release_400.headline': 'A maior versão que o TREK já teve.',
|
||||
'system_notice.release_400.intro':
|
||||
'O TREK ganha um celular e um livro. Dezenove pessoas escreveram esta — e com ela foram uns cento e cinquenta bugs relatados.',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK no celular',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'Tudo abaixo de 768px agora é uma interface própria — um dock de vidro, seus próprios painéis, seu próprio planejador. Abra o TREK no celular.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'O PDF do Journey virou um designer de álbuns de fotos. Ele monta o álbum quando você pede e depois sai do caminho.',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay aprende o resto',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Meios dias, banco de horas e dias flexíveis, férias escolares na grade — e um ano de férias que não precisa começar em janeiro.',
|
||||
'system_notice.release_400.feature_places_title': 'Lugares que se mostram, arquivos que saem',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'Fotos e descrição se preenchem sozinhas antes de você salvar um lugar. E seus uploads não precisam mais viver no disco onde o TREK roda.',
|
||||
'system_notice.release_400.footnote':
|
||||
'E estes são quatro deles. A 4.0.0 traz centenas de outras mudanças, de Collections e Atlas até todo o servidor por baixo.',
|
||||
'system_notice.release_400.note_eyebrow': 'Uma nota do mantenedor',
|
||||
'system_notice.release_400.note_title': 'Obrigado por usar o TREK.',
|
||||
'system_notice.release_400.note_body':
|
||||
'O TREK começou como uma ferramentinha para as minhas próprias viagens, escrita no tempo livre. E continua sendo: noites, fins de semana, as horas ao lado de um trabalho em tempo integral.\n\nPor um tempo era só eu. Não mais — dezenove pessoas entregaram esta versão, e milhares de pessoas chegaram com estrelas, issues, traduções e pull requests. Sou grato por cada parte disso.',
|
||||
'system_notice.release_400.promise_label': 'A promessa',
|
||||
'system_notice.release_400.promise_text':
|
||||
'O lado open source do TREK continua gratuito, para sempre. Sem planos pagos, sem assinaturas, sem pegadinhas. Prometido.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'A 4.0.0 levou semanas de noites longas — um app de celular, um designer de álbuns, uma migração de servidor, quase tudo escrito entre meia-noite e duas. Não é reclamação: eu amo construir isso. É só a resposta honesta de como uma versão desse tamanho sai de um projeto de tempo livre.',
|
||||
'system_notice.release_400.note_closing': 'Obrigado por estar aqui.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'O apoio é o que mantém isso de pé — servidores, domínios e as noites longas que viram versões como esta. Se o TREK vale algo para você, um café é o jeito mais direto de manter isso vivo.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Apoiar no Ko-fi',
|
||||
// The release modal. One stable set of keys: each big release swaps the copy in place.
|
||||
'system_notice.release_notes.eyebrow': 'Atualização instalada',
|
||||
'system_notice.release_notes.headline': 'Três coisas que o TREK agora faz sozinho.',
|
||||
'system_notice.release_notes.intro':
|
||||
'Uma API de lugares própria, viagens de carro planejadas de ponta a ponta e o seu histórico de localização de volta nas suas mãos.',
|
||||
'system_notice.release_notes.features_label': 'Os destaques',
|
||||
'system_notice.release_notes.features_aside': 'E não é só isso',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'O primeiro planejador de viagens open source que hospeda a própria API de lugares. 73,6 milhões de lugares, reconstruídos todo mês. Sem chave, sem cota.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Addon Viagem de carro',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'O modo viagem de carro planeja o próprio trajeto: a rota, a distância, as horas de direção e as paradas. É um addon, desligado até que um admin o ative.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Integração Dawarich',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'A alternativa self-hosted ao Google Timeline, agora visível dentro do TREK. O TREK lê, e apenas lê. Nada nunca é gravado de volta.',
|
||||
'system_notice.release_notes.footnote': 'E ainda uma longa lista de mudanças menores em todo o resto do TREK.',
|
||||
'system_notice.release_notes.notes_label': 'Notas da versão',
|
||||
'system_notice.release_notes.note_eyebrow': 'Uma nota do mantenedor',
|
||||
'system_notice.release_notes.note_title': 'Vocês são a razão de eu continuar construindo o TREK.',
|
||||
'system_notice.release_notes.note_body':
|
||||
'O TREK começou como uma ferramentinha para as minhas próprias viagens, escrita depois do trabalho porque eu queria um jeito melhor de planejá-las. E nunca parou de crescer de verdade. Quase tudo o que vocês usam foi construído tarde da noite, nos fins de semana, em trens, ao lado de um trabalho em tempo integral, e foram muitas as noites em que me perguntei, em silêncio, se alguém lá fora algum dia chegaria a abri-lo.',
|
||||
'system_notice.release_notes.promise_label': 'A promessa',
|
||||
'system_notice.release_notes.promise_lead': 'O TREK continua gratuito, para sempre.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'Cada recurso, cada atualização, para todo mundo. Sem planos pagos, sem assinaturas, sem pegadinhas.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'E aí vocês abriram. Em poucos meses eram milhares: estrelas, relatos de bugs, traduções para idiomas que eu não falo, pull requests de pessoas que nunca conheci. Até hoje a primeira coisa que faço toda manhã é olhar o repositório, e ainda não parece totalmente real.',
|
||||
'system_notice.release_notes.note_closing': 'Obrigado por estarem aqui. Um abraço, Maurice.',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'O TREK é gratuito e sempre vai ser, mas servidores, domínios e muitas noites em claro não são.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'Se o TREK ganhou um lugar nas suas viagens, me pague um café e ajude a fazer a próxima versão acontecer.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Apoiar no Ko-fi',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -55,40 +55,39 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.thank_you_support.highlight_community': 'Construït conjuntament amb la comunitat',
|
||||
'system_notice.thank_you_support.cta_bmc': 'Buy Me a Coffee',
|
||||
'system_notice.thank_you_support.cta_kofi': 'Dona suport a Ko-fi',
|
||||
'system_notice.release_400.eyebrow': 'Actualització instal·lada',
|
||||
'system_notice.release_400.tag': 'Versió',
|
||||
'system_notice.release_400.headline': 'La versió més gran que TREK ha tingut mai.',
|
||||
'system_notice.release_400.intro':
|
||||
'TREK guanya un telèfon, i un llibre. Dinou persones han escrit aquesta versió — i uns cent cinquanta errors reportats han desaparegut pel camí.',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK es fa mòbil',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'Tot el que hi ha per sota de 768px té ara la seva pròpia interfície — un dock de vidre, els seus fulls, el seu planificador. Obre TREK al telèfon.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
"El PDF de Journey s'ha convertit en un dissenyador de llibres de fotos. Compon el llibre quan l'hi demanes i després s'aparta.",
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay aprèn la resta',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Mitjos dies, dies de compensació i flexibles, vacances escolars a la graella — i un any de vacances que no ha de començar al gener.',
|
||||
'system_notice.release_400.feature_places_title': 'Els llocs es mostren, els fitxers marxen',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
"Les imatges i una descripció s'omplen soles abans que desis un lloc. I les teves pujades ja no han de viure al disc on s'executa TREK.",
|
||||
'system_notice.release_400.footnote':
|
||||
'I aquestes en són quatre. La 4.0.0 porta diversos centenars de canvis més, des de Collections i Atlas fins a tot el servidor de sota.',
|
||||
'system_notice.release_400.note_eyebrow': 'Una nota del mantenidor',
|
||||
'system_notice.release_400.note_title': 'Gràcies per utilitzar TREK.',
|
||||
'system_notice.release_400.note_body':
|
||||
"TREK va començar com una petita eina per als meus propis viatges, escrita al meu temps lliure. Encara ho és: vespres, caps de setmana, les hores al costat d'una feina a jornada completa.\n\nDurant un temps només hi era jo. Ja no — dinou persones han fet aquesta versió, i milers de vosaltres heu arribat amb estrelles, issues, traduccions i pull requests. Estic agraït per tot plegat.",
|
||||
'system_notice.release_400.promise_label': 'La promesa',
|
||||
'system_notice.release_400.promise_text':
|
||||
'La part de codi obert de TREK segueix sent gratuïta, per sempre. Sense nivells de pagament, sense subscripcions, sense lletra petita. Promès.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
"La 4.0.0 ha costat setmanes de nits llargues — una app de mòbil, un dissenyador de llibres, una migració del servidor, la major part escrita entre mitjanit i les dues. No és una queixa: m'encanta construir això. És només la resposta honesta a com surt una versió d'aquesta mida d'un projecte de temps lliure.",
|
||||
'system_notice.release_400.note_closing': 'Gràcies per ser aquí.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'El suport és el que fa que això funcioni — servidors, dominis i les nits llargues que es converteixen en versions com aquesta. Si TREK val alguna cosa per a tu, un cafè és la manera més directa de mantenir-ho en marxa.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Dona suport a Ko-fi',
|
||||
'system_notice.release_notes.eyebrow': 'Actualització instal·lada',
|
||||
'system_notice.release_notes.headline': 'Tres coses que TREK ja fa tot sol.',
|
||||
'system_notice.release_notes.intro':
|
||||
"La seva pròpia API de llocs, viatges per carretera planificats de principi a fi i el teu historial d'ubicacions de nou a les teves mans.",
|
||||
'system_notice.release_notes.features_label': 'Els protagonistes',
|
||||
'system_notice.release_notes.features_aside': 'I això no és tot',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'El primer planificador de viatges de codi obert que allotja la seva pròpia API de llocs. 73,6 milions de llocs, reconstruïts cada mes. Sense clau, sense quota.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Complement Roadtrip',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
"El mode viatge per carretera també planifica el trajecte en cotxe: la ruta, la distància, les hores al volant i les parades. És un complement, desactivat fins que un admin l'activi.",
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Integració amb Dawarich',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
"L'alternativa autoallotjada a Google Timeline, ara llegible des de TREK. TREK llegeix, i només llegeix. Mai no s'escriu res a Dawarich.",
|
||||
'system_notice.release_notes.footnote': 'I una llarga llista de canvis més petits a la resta de TREK.',
|
||||
'system_notice.release_notes.notes_label': 'Notes de la versió',
|
||||
'system_notice.release_notes.note_eyebrow': 'Una nota del mantenidor',
|
||||
'system_notice.release_notes.note_title': 'Sou el motiu pel qual continuo construint TREK.',
|
||||
'system_notice.release_notes.note_body':
|
||||
"TREK va néixer com una petita eina per als meus propis viatges, escrita després de la feina perquè volia una manera millor de planificar-los. En realitat, mai no ha deixat de créixer. Gairebé tot ho he construït a altes hores de la nit, els caps de setmana, als trens, al costat d'una feina a jornada completa, i més d'una vegada em vaig preguntar en silenci si algú, en algun lloc, l'obriria mai.",
|
||||
'system_notice.release_notes.promise_label': 'La promesa',
|
||||
'system_notice.release_notes.promise_lead': 'TREK continuarà sent gratuït, per sempre.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'Cada funcionalitat, cada actualització, per a tothom. Sense nivells de pagament, sense subscripcions, sense lletra petita.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
"I llavors el vau obrir. En pocs mesos éreu milers: estrelles, informes d'errors, traduccions a llengües que no parlo, pull requests de gent que no he conegut mai. El primer que faig cada matí continua sent mirar el repositori, i encara em costa creure-m'ho.",
|
||||
'system_notice.release_notes.note_closing': 'Gràcies per ser aquí. Una abraçada, Maurice.',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'TREK és gratuït i ho serà sempre, però els servidors, els dominis i tantes nits llargues no ho són.',
|
||||
'system_notice.release_notes.support_text':
|
||||
"Si s'ha guanyat un lloc als teus viatges, convida'm a un cafè i ajuda a fer que arribi la propera versió.",
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Dona suport a Ko-fi',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -54,41 +54,40 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.v3014_whitespace_collision.title': 'Vyžadována akce: konflikt uživatelského účtu',
|
||||
'system_notice.v3014_whitespace_collision.body':
|
||||
'Aktualizace 3.0.14 zjistila jeden nebo více konfliktů uživatelského jména nebo e-mailu způsobených mezerami na začátku nebo konci uložených hodnot. Dotčené účty byly automaticky přejmenovány. Zkontrolujte protokoly serveru na řádky začínající **[migration] WHITESPACE COLLISION** a zjistěte, které účty vyžadují kontrolu.',
|
||||
// 4.0.0 release modal — the release on the left, the note from the maintainer on the right
|
||||
'system_notice.release_400.eyebrow': 'Aktualizace nainstalována',
|
||||
'system_notice.release_400.tag': 'Vydání',
|
||||
'system_notice.release_400.headline': 'Největší vydání, jaké kdy TREK měl.',
|
||||
'system_notice.release_400.intro':
|
||||
'TREK dostává telefon a knihu. Tohle vydání psalo devatenáct lidí — a šlo s ním asi sto padesát nahlášených chyb.',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK jde do mobilu',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'Všechno pod 768px je teď vlastní rozhraní — skleněný dok, vlastní panely, vlastní plánovač cesty. Otevřete TREK v telefonu.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'Z PDF v Journey se stal návrhář fotoknihy. Rozvrhne knihu, když si řeknete, a pak jde stranou.',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay umí i zbytek',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Půldny, náhradní volno a flexi dny, školní prázdniny v mřížce — a rok dovolené, který nemusí začínat v lednu.',
|
||||
'system_notice.release_400.feature_places_title': 'Místa se ukážou, soubory se odstěhují',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'Obrázky a popis se doplní samy, ještě než místo uložíte. A nahrané soubory už nemusí ležet na disku, kde běží TREK.',
|
||||
'system_notice.release_400.footnote':
|
||||
'A tohle jsou čtyři z nich. 4.0.0 nese několik stovek dalších změn, od Collections a Atlas až po celý server pod nimi.',
|
||||
'system_notice.release_400.note_eyebrow': 'Slovo od autora',
|
||||
'system_notice.release_400.note_title': 'Děkuji, že používáte TREK.',
|
||||
'system_notice.release_400.note_body':
|
||||
'TREK začal jako malý nástroj pro mé vlastní cesty, psaný ve volném čase. Pořád jím je: večery, víkendy, hodiny vedle práce na plný úvazek.\n\nChvíli jsem na to byl sám. Už ne — tohle vydání dotáhlo devatenáct lidí a tisíce z vás přišly s hvězdičkami, issues, překlady a pull requesty. Jsem vděčný za každý kousek.',
|
||||
'system_notice.release_400.promise_label': 'Slib',
|
||||
'system_notice.release_400.promise_text':
|
||||
'Open source část TREK zůstane zdarma, navždy. Žádné placené verze, žádná předplatná, žádné háčky. Slibuji.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'4.0.0 stálo týdny pozdních nocí — aplikace do telefonu, návrhář knih, migrace serveru, většina psaná mezi půlnocí a druhou. Není to stížnost: baví mě to stavět. Je to jen upřímná odpověď na to, jak z projektu ve volném čase vznikne takhle velké vydání.',
|
||||
'system_notice.release_400.note_closing': 'Děkuji, že jste tady.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'Podpora je to, co tohle drží v chodu — servery, domény a pozdní noci, ze kterých vznikají vydání jako tohle. Pokud pro vás TREK něco znamená, káva je nejpřímější způsob, jak ho udržet v běhu.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Podpořit na Ko-fi',
|
||||
// The release modal. One stable set of keys: each big release swaps the copy in place.
|
||||
'system_notice.release_notes.eyebrow': 'Aktualizace nainstalována',
|
||||
'system_notice.release_notes.headline': 'Tři věci, které TREK teď zvládne sám.',
|
||||
'system_notice.release_notes.intro':
|
||||
'Vlastní API pro místa, cesty autem naplánované od začátku do konce a vaše historie polohy opět ve vašich rukou.',
|
||||
'system_notice.release_notes.features_label': 'Hlavní novinky',
|
||||
'system_notice.release_notes.features_aside': 'Zdaleka ne všechno',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'První open source plánovač cest, který provozuje vlastní API pro místa. 73,6 milionu míst, každý měsíc nově sestavených. Žádný klíč, žádná kvóta.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Doplněk Cesta autem',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'Režim Cesta autem naplánuje i samotnou jízdu: trasu, vzdálenost, hodiny za volantem i zastávky. Jde o doplněk, který zůstává vypnutý, dokud ho nezapne správce.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Integrace Dawarich',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'Self-hosted odpověď na Google Timeline, teď čitelná přímo v TREK. TREK čte, a jen čte. Nic se nikdy nezapisuje zpět.',
|
||||
'system_notice.release_notes.footnote': 'A k tomu dlouhý seznam menších změn napříč zbytkem TREK.',
|
||||
'system_notice.release_notes.notes_label': 'Poznámky k vydání',
|
||||
'system_notice.release_notes.note_eyebrow': 'Slovo od autora',
|
||||
'system_notice.release_notes.note_title': 'Vy jste důvod, proč na TREK pořád pracuji.',
|
||||
'system_notice.release_notes.note_body':
|
||||
'TREK začal jako malý nástroj pro mé vlastní cesty, psaný po práci, protože jsem je chtěl plánovat lépe. Vlastně nikdy nepřestal růst. Skoro všechno, co používáte, vzniklo pozdě v noci, o víkendech, ve vlacích, vedle práce na plný úvazek, a bylo spoustu večerů, kdy jsem se potichu ptal, jestli ho tam venku vůbec někdy někdo otevře.',
|
||||
'system_notice.release_notes.promise_label': 'Slib',
|
||||
'system_notice.release_notes.promise_lead': 'TREK zůstane zdarma, navždy.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'Každá funkce, každá aktualizace, pro všechny. Žádné placené verze, žádná předplatná, žádné háčky.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'A pak jste ho otevřeli. Během pár měsíců vás byly tisíce: hvězdičky, hlášení chyb, překlady do jazyků, kterými nemluvím, pull requesty od lidí, které jsem nikdy nepotkal. Každé ráno se pořád nejdřív podívám do repozitáře a pořád mi to nepřijde úplně skutečné.',
|
||||
'system_notice.release_notes.note_closing': 'Děkuji, že jste tady. Váš Maurice',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'TREK je a vždycky bude zdarma, ale servery, domény a spousta pozdních nocí zdarma nejsou.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'Pokud si TREK získal místo na vašich cestách, kupte mi kávu a pomozte, aby přišlo i další vydání.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Podpořit na Ko-fi',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -55,41 +55,40 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.v3014_whitespace_collision.title': 'Aktion erforderlich: Benutzerkontokonflikt',
|
||||
'system_notice.v3014_whitespace_collision.body':
|
||||
'Das 3.0.14-Upgrade hat einen oder mehrere Konflikte bei Benutzernamen oder E-Mail-Adressen festgestellt, die durch führende oder nachgestellte Leerzeichen in gespeicherten Konten verursacht wurden. Betroffene Konten wurden automatisch umbenannt. Prüfe die Serverprotokolle auf Zeilen, die mit **[migration] WHITESPACE COLLISION** beginnen, um die betroffenen Konten zu identifizieren.',
|
||||
// 4.0.0-Release-Modal — links das Release, rechts das Wort vom Maintainer
|
||||
'system_notice.release_400.eyebrow': 'Update installiert',
|
||||
'system_notice.release_400.tag': 'Release',
|
||||
'system_notice.release_400.headline': 'Das größte Release, das TREK je hatte.',
|
||||
'system_notice.release_400.intro':
|
||||
'TREK bekommt ein Handy und ein Buch. Neunzehn Leute haben daran geschrieben — und rund hundertfünfzig gemeldete Bugs sind mitgekommen.',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK wird mobil',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'Alles unter 768px ist jetzt eine eigene Oberfläche — ein Glas-Dock, eigene Sheets, ein eigener Trip-Planer. Öffne TREK auf deinem Handy.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'Aus dem Journey-PDF wurde ein Fotobuch-Designer. Er setzt das Buch, wenn du ihn darum bittest, und hält sich danach raus.',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay lernt den Rest',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Halbe Tage, Überstunden- und Gleittage, Schulferien im Raster — und ein Urlaubsjahr, das nicht im Januar anfangen muss.',
|
||||
'system_notice.release_400.feature_places_title': 'Orte zeigen sich, Dateien ziehen aus',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'Bilder und eine Beschreibung füllen sich von selbst, bevor du einen Ort speicherst. Und deine Uploads müssen nicht mehr auf der Platte liegen, auf der TREK läuft.',
|
||||
'system_notice.release_400.footnote':
|
||||
'Und das sind vier davon. 4.0.0 bringt mehrere hundert weitere Änderungen mit, von Collections und Atlas bis zum ganzen Server darunter.',
|
||||
'system_notice.release_400.note_eyebrow': 'Ein Wort vom Maintainer',
|
||||
'system_notice.release_400.note_title': 'Danke, dass du TREK nutzt.',
|
||||
'system_notice.release_400.note_body':
|
||||
'TREK hat als kleines Tool für meine eigenen Reisen angefangen, geschrieben in meiner Freizeit. Das ist es immer noch: Abende, Wochenenden, die Stunden neben einem Vollzeitjob.\n\nEine Weile war ich allein damit. Jetzt nicht mehr — neunzehn Leute haben dieses Release gebaut, und Tausende von euch kamen dazu, mit Sternen, Issues, Übersetzungen und Pull Requests. Ich bin für jedes Stück davon dankbar.',
|
||||
'system_notice.release_400.promise_label': 'Das Versprechen',
|
||||
'system_notice.release_400.promise_text':
|
||||
'Die Open-Source-Seite von TREK bleibt kostenlos, für immer. Keine Paid Tiers, keine Abos, kein Haken. Versprochen.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'4.0.0 hat Wochen an späten Nächten gekostet — eine Handy-App, ein Buch-Designer, eine Server-Migration, das meiste zwischen Mitternacht und zwei geschrieben. Keine Klage: Ich baue das gern. Es ist nur die ehrliche Antwort darauf, wie ein Release dieser Größe aus einem Freizeitprojekt kommt.',
|
||||
'system_notice.release_400.note_closing': 'Danke, dass du dabei bist.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'Unterstützung ist das, was das hier am Laufen hält — Server, Domains und die späten Nächte, aus denen Releases wie dieses werden. Wenn TREK dir etwas wert ist, ist ein Kaffee der direkteste Weg, es weiterlaufen zu lassen.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Ko-fi unterstützen',
|
||||
// The release modal. One stable set of keys: each big release swaps the copy in place.
|
||||
'system_notice.release_notes.eyebrow': 'Update installiert',
|
||||
'system_notice.release_notes.headline': 'Drei Dinge, die TREK jetzt selbst erledigt.',
|
||||
'system_notice.release_notes.intro':
|
||||
'Eine eigene API für Orte, Roadtrips von Anfang bis Ende geplant und dein Standortverlauf wieder in deiner Hand.',
|
||||
'system_notice.release_notes.features_label': 'Die Highlights',
|
||||
'system_notice.release_notes.features_aside': 'Längst nicht alles',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'Der erste Open-Source-Reiseplaner, der seine eigene API für Orte betreibt. 73,6 Millionen Orte, jeden Monat neu aufgebaut. Kein Schlüssel, kein Kontingent.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Roadtrip-Addon',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'Der Roadtrip-Modus plant die Fahrt selbst: die Route, ihre Länge, die Fahrzeit und die Stopps. Ein Addon, das aus bleibt, bis ein Admin es einschaltet.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Dawarich-Integration',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'Die selbst gehostete Antwort auf Google Timeline, jetzt direkt in TREK lesbar. TREK liest, und nur das. Zurückgeschrieben wird nie etwas.',
|
||||
'system_notice.release_notes.footnote': 'Dazu kommt eine lange Liste kleinerer Änderungen überall sonst in TREK.',
|
||||
'system_notice.release_notes.notes_label': 'Release Notes',
|
||||
'system_notice.release_notes.note_eyebrow': 'Ein Wort vom Maintainer',
|
||||
'system_notice.release_notes.note_title': 'Du bist der Grund, warum ich TREK weiterbaue.',
|
||||
'system_notice.release_notes.note_body':
|
||||
'TREK hat als kleines Tool für meine eigenen Reisen angefangen, geschrieben nach Feierabend, weil ich sie besser planen wollte. Aufgehört zu wachsen hat es eigentlich nie. Fast alles, was du nutzt, ist spät in der Nacht entstanden, am Wochenende, im Zug, neben einem Vollzeitjob, und an so manchem Abend habe ich mich still gefragt, ob es da draußen überhaupt jemals jemand öffnen würde.',
|
||||
'system_notice.release_notes.promise_label': 'Das Versprechen',
|
||||
'system_notice.release_notes.promise_lead': 'TREK bleibt kostenlos, für immer.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'Jede Funktion, jedes Update, für alle. Keine Paid Tiers, keine Abos, kein Haken.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'Dann kamt ihr. Innerhalb weniger Monate wart ihr Tausende: Sterne, Bug-Reports, Übersetzungen in Sprachen, die ich nicht spreche, Pull Requests von Leuten, die ich nie getroffen habe. Ich schaue noch immer jeden Morgen als Erstes ins Repository, und so richtig real fühlt es sich bis heute nicht an.',
|
||||
'system_notice.release_notes.note_closing': 'Danke, dass du dabei bist. Viele Grüße, Maurice.',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'TREK ist kostenlos und wird es immer bleiben, aber Server, Domains und viele späte Nächte sind es nicht.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'Wenn TREK sich einen Platz auf deinen Reisen verdient hat, spendier mir einen Kaffee und hilf mit, dass auch das nächste Release kommt.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Ko-fi unterstützen',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -50,42 +50,41 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.thank_you_support.highlight_community': 'Built together with the community',
|
||||
'system_notice.thank_you_support.cta_bmc': 'Buy Me a Coffee',
|
||||
'system_notice.thank_you_support.cta_kofi': 'Support on Ko-fi',
|
||||
// 4.0.0 release modal — the release on the left, the note from the maintainer on the right
|
||||
'system_notice.release_400.eyebrow': 'Update installed',
|
||||
'system_notice.release_400.tag': 'Release',
|
||||
'system_notice.release_400.headline': 'The biggest release TREK has ever had.',
|
||||
'system_notice.release_400.intro':
|
||||
'TREK gets a phone, and a book. Nineteen people wrote this one — and about a hundred and fifty reported bugs went with it.',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK goes mobile',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'Everything under 768px is its own interface now — a glass dock, its own sheets, its own trip planner. Open TREK on your phone.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'The Journey PDF became a photo book designer. It lays the book out when you ask it to, then gets out of the way.',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay learns the rest',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Half days, comp and flex days, school holidays on the grid — and a leave year that does not have to start in January.',
|
||||
'system_notice.release_400.feature_places_title': 'Places show themselves, files move out',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'Pictures and a description fill themselves in before you save a place. And your uploads no longer have to live on the disk TREK runs on.',
|
||||
'system_notice.release_400.footnote':
|
||||
'And these are four of them. 4.0.0 carries several hundred further changes, from Collections and Atlas to the whole server underneath.',
|
||||
'system_notice.release_400.note_eyebrow': 'A note from the maintainer',
|
||||
'system_notice.release_400.note_title': 'Thank you for using TREK.',
|
||||
'system_notice.release_400.note_body':
|
||||
'TREK started as a little tool for my own trips, written in my spare time. It still is: evenings, weekends, the hours next to a full-time job.\n\nFor a while it was only me. Not anymore — nineteen people shipped this release, and thousands of you arrived with stars, issues, translations and pull requests. I am grateful for every part of it.',
|
||||
'system_notice.release_400.promise_label': 'The promise',
|
||||
'system_notice.release_400.promise_text':
|
||||
'The open-source side of TREK stays free, forever. No paid tiers, no subscriptions, no catch. Promised.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'4.0.0 took weeks of late nights — a phone app, a book designer, a server migration, most of it written between midnight and two. Not a complaint: I love building this. It is just the honest answer to how a release this size comes out of a spare-time project.',
|
||||
'system_notice.release_400.note_closing': 'Thank you for being here.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'Support is what keeps this running — servers, domains, and the late nights that turn into releases like this one. If TREK is worth something to you, a coffee is the most direct way to keep it going.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Support on Ko-fi',
|
||||
// The release modal. One stable set of keys: each big release swaps the copy in place.
|
||||
'system_notice.release_notes.eyebrow': 'Update installed',
|
||||
'system_notice.release_notes.headline': 'Three things TREK now does on its own.',
|
||||
'system_notice.release_notes.intro':
|
||||
'Its own place API, road trips planned end to end, and your location history back in your hands.',
|
||||
'system_notice.release_notes.features_label': 'The headliners',
|
||||
'system_notice.release_notes.features_aside': 'Far from everything',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'The first open source travel planner that hosts its own place API. 73.6 million places, rebuilt monthly. No key, no quota.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Roadtrip Addon',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'Road trip mode plans the drive itself: the route, its distance, its hours and its stops. An addon, off until an admin turns it on.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Dawarich Integration',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'The self-hosted answer to Google Timeline, now readable inside TREK. TREK reads, and only reads. Nothing is ever written back.',
|
||||
'system_notice.release_notes.footnote': 'Plus a long list of smaller changes across the rest of TREK.',
|
||||
'system_notice.release_notes.notes_label': 'Release notes',
|
||||
'system_notice.release_notes.note_eyebrow': 'A note from the maintainer',
|
||||
'system_notice.release_notes.note_title': 'You are the reason I keep building TREK.',
|
||||
'system_notice.release_notes.note_body':
|
||||
'TREK began as a small tool for my own trips, written after work because I wanted a better way to plan them. It never really stopped growing. Almost everything you use was built late at night, on weekends, on trains, next to a full-time job, and there were plenty of evenings I quietly wondered whether anyone out there would ever open it.',
|
||||
'system_notice.release_notes.promise_label': 'The promise',
|
||||
'system_notice.release_notes.promise_lead': 'TREK stays free, forever.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'Every feature, every update, for everyone. No paid tiers, no subscriptions, no catch.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'Then you did. Within a few months there were thousands of you: stars, bug reports, translations into languages I do not speak, pull requests from people I have never met. I still check the repository first thing every morning, and it still does not quite feel real.',
|
||||
'system_notice.release_notes.note_closing': 'Thank you for being here, from Maurice.',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'TREK is free and always will be, but servers, domains and a lot of late nights are not.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'If it has earned a place in your trips, buy me a coffee and help keep the next release coming.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Support on Ko-fi',
|
||||
'system_notice.pager.prev': 'Previous notice',
|
||||
'system_notice.pager.next': 'Next notice',
|
||||
'system_notice.pager.counter': '{current} / {total}',
|
||||
|
||||
@@ -54,41 +54,40 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.v3014_whitespace_collision.title': 'Acción requerida: conflicto de cuenta de usuario',
|
||||
'system_notice.v3014_whitespace_collision.body':
|
||||
'La actualización 3.0.14 detectó uno o más conflictos de nombre de usuario o correo electrónico causados por espacios en blanco al inicio o al final de los valores almacenados. Las cuentas afectadas se renombraron automáticamente. Revisa los registros del servidor en busca de líneas que empiecen por **[migration] WHITESPACE COLLISION** para identificar qué cuentas necesitan revisión.',
|
||||
// 4.0.0 release modal — the release on the left, the note from the maintainer on the right
|
||||
'system_notice.release_400.eyebrow': 'Actualización instalada',
|
||||
'system_notice.release_400.tag': 'Versión',
|
||||
'system_notice.release_400.headline': 'La mayor versión que TREK ha tenido jamás.',
|
||||
'system_notice.release_400.intro':
|
||||
'TREK recibe un móvil y un libro. La escribieron diecinueve personas — y con ella se fueron unos ciento cincuenta bugs.',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK en el móvil',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'Todo por debajo de 768px es ya una interfaz propia — un dock de cristal, sus propios paneles, su propio planificador. Abre TREK en tu móvil.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'El PDF de Journey se convirtió en un diseñador de fotolibros. Maqueta el libro cuando se lo pides y luego se aparta.',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay aprende el resto',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Medios días, días de compensación y flexibles, vacaciones escolares en la rejilla — y un año que no tiene que empezar en enero.',
|
||||
'system_notice.release_400.feature_places_title': 'Lugares que se muestran, archivos que salen',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'Las fotos y la descripción se rellenan solas antes de guardar un lugar. Y tus archivos ya no tienen que vivir en el disco donde corre TREK.',
|
||||
'system_notice.release_400.footnote':
|
||||
'Y estas son cuatro. La 4.0.0 trae varios cientos de cambios más, desde Collections y Atlas hasta todo el servidor por debajo.',
|
||||
'system_notice.release_400.note_eyebrow': 'Una nota del desarrollador',
|
||||
'system_notice.release_400.note_title': 'Gracias por usar TREK.',
|
||||
'system_notice.release_400.note_body':
|
||||
'TREK empezó como una pequeña herramienta para mis propios viajes, escrita en mi tiempo libre. Y lo sigue siendo: tardes, fines de semana, las horas junto a un trabajo a jornada completa.\n\nDurante un tiempo fui solo yo. Ya no — diecinueve personas sacaron esta versión, y miles de personas llegaron con estrellas, issues, traducciones y pull requests. Estoy agradecido por cada parte.',
|
||||
'system_notice.release_400.promise_label': 'La promesa',
|
||||
'system_notice.release_400.promise_text':
|
||||
'La parte open source de TREK sigue siendo gratis, para siempre. Sin planes de pago, sin suscripciones, sin trampa. Prometido.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'La 4.0.0 costó semanas de noches en vela — una app de móvil, un diseñador de libros, una migración del servidor, casi todo escrito entre medianoche y las dos. No es una queja: me encanta hacer esto. Es solo la respuesta honesta a cómo sale una versión así de un proyecto de tiempo libre.',
|
||||
'system_notice.release_400.note_closing': 'Gracias por estar aquí.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'El apoyo es lo que mantiene esto en marcha — servidores, dominios y las noches en vela que acaban en versiones como esta. Si TREK vale algo para ti, un café es la forma más directa de que siga.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Apóyame en Ko-fi',
|
||||
// The release modal. One stable set of keys: each big release swaps the copy in place.
|
||||
'system_notice.release_notes.eyebrow': 'Actualización instalada',
|
||||
'system_notice.release_notes.headline': 'Tres cosas que TREK ya hace por sí solo.',
|
||||
'system_notice.release_notes.intro':
|
||||
'Su propia API de lugares, viajes por carretera planificados de principio a fin y tu historial de ubicaciones de nuevo en tus manos.',
|
||||
'system_notice.release_notes.features_label': 'Los protagonistas',
|
||||
'system_notice.release_notes.features_aside': 'Y eso no es todo',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'El primer planificador de viajes open source que aloja su propia API de lugares. 73,6 millones de lugares, reconstruidos cada mes. Sin clave, sin cuota.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Addon Roadtrip',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'El modo viaje por carretera también planifica el trayecto en coche: la ruta, la distancia, las horas al volante y las paradas. Es un addon, desactivado hasta que un admin lo active.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Integración con Dawarich',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'La alternativa autoalojada a Google Timeline, ahora legible desde TREK. TREK lee, y solo lee. Nunca se escribe nada en Dawarich.',
|
||||
'system_notice.release_notes.footnote': 'Y una larga lista de cambios más pequeños en el resto de TREK.',
|
||||
'system_notice.release_notes.notes_label': 'Notas de versión',
|
||||
'system_notice.release_notes.note_eyebrow': 'Una nota del desarrollador',
|
||||
'system_notice.release_notes.note_title': 'Sois la razón por la que sigo construyendo TREK.',
|
||||
'system_notice.release_notes.note_body':
|
||||
'TREK nació como una pequeña herramienta para mis propios viajes, escrita después del trabajo porque quería una forma mejor de planificarlos. En realidad, nunca ha dejado de crecer. Casi todo lo he construido a altas horas de la noche, los fines de semana, en trenes, junto a un trabajo a jornada completa, y más de una vez me pregunté en silencio si alguien, en algún lugar, llegaría a abrirlo.',
|
||||
'system_notice.release_notes.promise_label': 'La promesa',
|
||||
'system_notice.release_notes.promise_lead': 'TREK seguirá siendo gratis, para siempre.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'Cada función, cada actualización, para todo el mundo. Sin planes de pago, sin suscripciones, sin trampa.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'Y entonces lo abristeis. En pocos meses erais miles: estrellas, informes de errores, traducciones a idiomas que no hablo, pull requests de gente a la que nunca he conocido. Lo primero que hago cada mañana sigue siendo mirar el repositorio, y todavía me cuesta creérmelo.',
|
||||
'system_notice.release_notes.note_closing': 'Gracias por estar aquí. Un abrazo, Maurice.',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'TREK es gratis y siempre lo será, pero los servidores, los dominios y tantas noches en vela no lo son.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'Si se ha ganado un sitio en tus viajes, invítame a un café y ayuda a que llegue la próxima versión.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Apóyame en Ko-fi',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -54,40 +54,39 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.v3014_whitespace_collision.title': 'Action requise : conflit de compte utilisateur',
|
||||
'system_notice.v3014_whitespace_collision.body':
|
||||
"La mise à niveau 3.0.14 a détecté un ou plusieurs conflits de nom d'utilisateur ou d'adresse e-mail causés par des espaces en début ou en fin de valeur dans les comptes enregistrés. Les comptes concernés ont été renommés automatiquement. Consultez les journaux du serveur pour les lignes commençant par **[migration] WHITESPACE COLLISION** afin d'identifier les comptes nécessitant une vérification.",
|
||||
'system_notice.release_400.eyebrow': 'Mise à jour installée',
|
||||
'system_notice.release_400.tag': 'Version',
|
||||
'system_notice.release_400.headline': 'La plus grande version de TREK à ce jour.',
|
||||
'system_notice.release_400.intro':
|
||||
'TREK gagne un téléphone, et un livre. Dix-neuf personnes ont écrit cette version — et environ cent cinquante bugs signalés ont disparu au passage.',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK passe au mobile',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'Tout ce qui est sous 768px a désormais sa propre interface — un dock en verre, ses feuilles, son planificateur. Ouvre TREK sur ton téléphone.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
"Le PDF de Journey est devenu un concepteur de livre photo. Il met le livre en page quand tu le demandes, puis s'efface.",
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay apprend le reste',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Demi-journées, récup et RTT, vacances scolaires dans la grille — et une année de congés qui ne commence pas forcément en janvier.',
|
||||
'system_notice.release_400.feature_places_title': 'Les lieux se présentent, les fichiers déménagent',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'Photos et description se remplissent toutes seules avant que tu enregistres un lieu. Et tes fichiers ne sont plus obligés de vivre sur le disque où tourne TREK.',
|
||||
'system_notice.release_400.footnote':
|
||||
"Et ce ne sont que quatre d'entre eux. 4.0.0 apporte plusieurs centaines d'autres changements, de Collections et Atlas jusqu'au serveur en dessous.",
|
||||
'system_notice.release_400.note_eyebrow': 'Un mot du mainteneur',
|
||||
'system_notice.release_400.note_title': "Merci d'utiliser TREK.",
|
||||
'system_notice.release_400.note_body':
|
||||
"TREK a commencé comme un petit outil pour mes propres voyages, écrit sur mon temps libre. Ça l'est toujours : le soir, le week-end, les heures à côté d'un travail à temps plein.\n\nPendant un temps, il n'y avait que moi. Plus maintenant — dix-neuf personnes ont livré cette version, et vous êtes des milliers à être arrivés avec des étoiles, des issues, des traductions et des pull requests. Je suis reconnaissant pour tout ça.",
|
||||
'system_notice.release_400.promise_label': 'La promesse',
|
||||
'system_notice.release_400.promise_text':
|
||||
"Le côté open source de TREK reste gratuit, pour toujours. Pas de formules payantes, pas d'abonnements, aucun piège. Promis.",
|
||||
'system_notice.release_400.note_body_after':
|
||||
"4.0.0 a demandé des semaines de nuits blanches — une app mobile, un concepteur de livre, une migration serveur, l'essentiel écrit entre minuit et deux heures. Ce n'est pas une plainte : j'adore construire ça. C'est juste la réponse honnête à comment une version de cette taille sort d'un projet de temps libre.",
|
||||
'system_notice.release_400.note_closing': "Merci d'être là.",
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'Le soutien est ce qui fait tourner tout ça — serveurs, domaines, et les nuits blanches qui deviennent des versions comme celle-ci. Si TREK vaut quelque chose pour toi, un café est le moyen le plus direct de continuer.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Soutenir sur Ko-fi',
|
||||
'system_notice.release_notes.eyebrow': 'Mise à jour installée',
|
||||
'system_notice.release_notes.headline': 'Trois choses que TREK fait désormais tout seul.',
|
||||
'system_notice.release_notes.intro':
|
||||
'Sa propre API de lieux, des road trips planifiés de bout en bout et ton historique de positions de retour entre tes mains.',
|
||||
'system_notice.release_notes.features_label': "Les têtes d'affiche",
|
||||
'system_notice.release_notes.features_aside': "Et ce n'est pas tout",
|
||||
'system_notice.release_notes.feature_places_title': 'API TREK Places',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'Le premier planificateur de voyage open source qui héberge sa propre API de lieux. 73,6 millions de lieux, reconstruits chaque mois. Sans clé, sans quota.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Addon Roadtrip',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
"Le mode road trip planifie aussi le trajet en voiture : l'itinéraire, la distance, les heures de route et les arrêts. C'est un addon, désactivé tant qu'un admin ne l'active pas.",
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Intégration Dawarich',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
"L'alternative auto-hébergée à Google Timeline, désormais lisible depuis TREK. TREK lit, et ne fait que lire. Rien n'est jamais réécrit dans Dawarich.",
|
||||
'system_notice.release_notes.footnote': 'Et une longue liste de changements plus discrets dans le reste de TREK.',
|
||||
'system_notice.release_notes.notes_label': 'Notes de version',
|
||||
'system_notice.release_notes.note_eyebrow': 'Un mot du mainteneur',
|
||||
'system_notice.release_notes.note_title': "C'est pour vous que je continue à construire TREK.",
|
||||
'system_notice.release_notes.note_body':
|
||||
"TREK est né comme un petit outil pour mes propres voyages, écrit après le travail parce que je voulais une meilleure façon de les préparer. Il n'a jamais vraiment cessé de grandir. Presque tout ce qui existe aujourd'hui a été construit tard le soir, le week-end, dans le train, à côté d'un travail à temps plein, et bien des soirs je me suis demandé en silence si quelqu'un, quelque part, l'ouvrirait un jour.",
|
||||
'system_notice.release_notes.promise_label': 'La promesse',
|
||||
'system_notice.release_notes.promise_lead': 'TREK reste gratuit, pour toujours.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
"Chaque fonctionnalité, chaque mise à jour, pour tout le monde. Pas de formules payantes, pas d'abonnements, aucun piège.",
|
||||
'system_notice.release_notes.note_body_after':
|
||||
"Et puis vous l'avez ouvert. En quelques mois, vous étiez des milliers : des étoiles, des rapports de bugs, des traductions dans des langues que je ne parle pas, des pull requests de personnes que je n'ai jamais rencontrées. Chaque matin, la première chose que je fais est encore d'aller voir le dépôt, et j'ai toujours du mal à y croire.",
|
||||
'system_notice.release_notes.note_closing': "Merci d'être là. Amicalement, Maurice.",
|
||||
'system_notice.release_notes.support_lead':
|
||||
'TREK est gratuit et le restera toujours, mais les serveurs, les noms de domaine et toutes ces nuits blanches, eux, ne le sont pas.',
|
||||
'system_notice.release_notes.support_text':
|
||||
"Si TREK s'est fait une place dans tes voyages, offre-moi un café et aide la prochaine version à voir le jour.",
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Soutenir sur Ko-fi',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -56,40 +56,39 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.pager.counter': '{current} / {total}',
|
||||
'system_notice.pager.goto': 'Μετάβαση στην ειδοποίηση {n}',
|
||||
'system_notice.pager.position': 'Ειδοποίηση {current} από {total}',
|
||||
'system_notice.release_400.eyebrow': 'Ενημερώθηκε',
|
||||
'system_notice.release_400.tag': 'Έκδοση',
|
||||
'system_notice.release_400.headline': 'Η μεγαλύτερη έκδοση που είχε ποτέ το TREK.',
|
||||
'system_notice.release_400.intro':
|
||||
'Το TREK αποκτά τηλέφωνο, και βιβλίο. Αυτή την έκδοση την έγραψαν δεκαεννέα άτομα — και μαζί της έφυγαν περίπου εκατόν πενήντα σφάλματα που αναφέρατε.',
|
||||
'system_notice.release_400.feature_mobile_title': 'Το TREK σε κινητό',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'Οτιδήποτε κάτω από 768px έχει πλέον δικό του περιβάλλον — ένα γυάλινο dock, δικά του πάνελ, δικό του σχεδιαστή ταξιδιού. Ανοίξτε το TREK στο κινητό σας.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'Το PDF του Journey έγινε σχεδιαστής βιβλίου φωτογραφιών. Στήνει το βιβλίο όταν του το ζητήσετε, και μετά κάνει στην άκρη.',
|
||||
'system_notice.release_400.feature_vacay_title': 'Το Vacay μαθαίνει τα υπόλοιπα',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Μισές ημέρες, ρεπό και ευέλικτες ημέρες, σχολικές αργίες στο πλέγμα — και ένα έτος αδειών που δεν χρειάζεται να ξεκινά τον Ιανουάριο.',
|
||||
'system_notice.release_400.feature_places_title': 'Οι τοποθεσίες συστήνονται, τα αρχεία φεύγουν',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'Εικόνες και περιγραφή συμπληρώνονται μόνες τους πριν αποθηκεύσετε μια τοποθεσία. Και τα αρχεία σας δεν χρειάζεται πια να μένουν στον δίσκο όπου τρέχει το TREK.',
|
||||
'system_notice.release_400.footnote':
|
||||
'Και αυτές είναι τέσσερις. Η 4.0.0 φέρνει αρκετές εκατοντάδες ακόμη αλλαγές, από τα Collections και το Atlas μέχρι όλο τον server από κάτω.',
|
||||
'system_notice.release_400.note_eyebrow': 'Μια σημείωση από τον δημιουργό',
|
||||
'system_notice.release_400.note_title': 'Ευχαριστώ που χρησιμοποιείτε το TREK.',
|
||||
'system_notice.release_400.note_body':
|
||||
'Το TREK ξεκίνησε ως ένα μικρό εργαλείο για τα δικά μου ταξίδια, γραμμένο στον ελεύθερό μου χρόνο. Έτσι είναι ακόμα: βράδια, σαββατοκύριακα, οι ώρες δίπλα σε μια δουλειά πλήρους απασχόλησης.\n\nΓια κάποιο διάστημα ήμουν μόνο εγώ. Όχι πια — δεκαεννέα άτομα έβγαλαν αυτή την έκδοση, και χιλιάδες από εσάς ήρθατε με αστέρια, αναφορές, μεταφράσεις και pull requests. Είμαι ευγνώμων για κάθε κομμάτι της.',
|
||||
'system_notice.release_400.promise_label': 'Η υπόσχεση',
|
||||
'system_notice.release_400.promise_text':
|
||||
'Η ανοιχτού κώδικα πλευρά του TREK μένει δωρεάν, για πάντα. Καμία έκδοση επί πληρωμή, καμία συνδρομή, καμία παγίδα. Το υπόσχομαι.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'Η 4.0.0 πήρε εβδομάδες από ξενύχτια — μια εφαρμογή για κινητό, έναν σχεδιαστή βιβλίου, μια μετάβαση του server, τα περισσότερα γραμμένα ανάμεσα στα μεσάνυχτα και τις δύο. Δεν είναι παράπονο: μου αρέσει να το φτιάχνω. Είναι απλώς η ειλικρινής απάντηση στο πώς βγαίνει μια τόσο μεγάλη έκδοση από ένα έργο του ελεύθερου χρόνου.',
|
||||
'system_notice.release_400.note_closing': 'Σας ευχαριστώ που είστε εδώ.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'Η στήριξη είναι αυτό που κρατά όλο αυτό ζωντανό — servers, domains και οι ξενύχτιες που γίνονται εκδόσεις σαν κι αυτή. Αν το TREK αξίζει κάτι για εσάς, ένας καφές είναι ο πιο άμεσος τρόπος να συνεχίσει.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Στηρίξτε στο Ko-fi',
|
||||
'system_notice.release_notes.eyebrow': 'Ενημερώθηκε',
|
||||
'system_notice.release_notes.headline': 'Τρία πράγματα που το TREK κάνει πλέον μόνο του.',
|
||||
'system_notice.release_notes.intro':
|
||||
'Δικό του API τοποθεσιών, οδικά ταξίδια σχεδιασμένα από την αρχή ως το τέλος και το ιστορικό των μετακινήσεών σας ξανά στα χέρια σας.',
|
||||
'system_notice.release_notes.features_label': 'Τα σημαντικότερα',
|
||||
'system_notice.release_notes.features_aside': 'Και δεν είναι μόνο αυτά',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'Ο πρώτος σχεδιαστής ταξιδιών ανοιχτού κώδικα που φιλοξενεί το δικό του API τοποθεσιών. 73,6 εκατομμύρια τοποθεσίες, που ξαναχτίζονται κάθε μήνα. Χωρίς κλειδί, χωρίς όρια χρήσης.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Πρόσθετο «Οδικό ταξίδι»',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'Η λειτουργία οδικού ταξιδιού σχεδιάζει την ίδια την οδήγηση: τη διαδρομή, την απόσταση, τις ώρες και τις στάσεις της. Είναι πρόσθετο και μένει ανενεργό μέχρι να το ενεργοποιήσει ένας διαχειριστής.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Ενσωμάτωση Dawarich',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'Η εναλλακτική του Google Timeline που φιλοξενείτε μόνοι σας, τώρα ορατή μέσα από το TREK. Το TREK διαβάζει, και μόνο διαβάζει. Τίποτα δεν γράφεται ποτέ πίσω.',
|
||||
'system_notice.release_notes.footnote': 'Και ακόμη μια μεγάλη λίστα με μικρότερες αλλαγές σε όλο το υπόλοιπο TREK.',
|
||||
'system_notice.release_notes.notes_label': 'Σημειώσεις έκδοσης',
|
||||
'system_notice.release_notes.note_eyebrow': 'Μια σημείωση από τον δημιουργό',
|
||||
'system_notice.release_notes.note_title': 'Εσείς είστε ο λόγος που συνεχίζω να φτιάχνω το TREK.',
|
||||
'system_notice.release_notes.note_body':
|
||||
'Το TREK ξεκίνησε ως ένα μικρό εργαλείο για τα δικά μου ταξίδια, γραμμένο μετά τη δουλειά επειδή ήθελα έναν καλύτερο τρόπο να τα οργανώνω. Από τότε δεν σταμάτησε ποτέ πραγματικά να μεγαλώνει. Σχεδόν ό,τι χρησιμοποιείτε φτιάχτηκε αργά τη νύχτα, τα σαββατοκύριακα, στα τρένα, δίπλα σε μια δουλειά πλήρους απασχόλησης, και ήταν πολλά τα βράδια που αναρωτιόμουν σιωπηλά αν θα το άνοιγε ποτέ κανείς εκεί έξω.',
|
||||
'system_notice.release_notes.promise_label': 'Η υπόσχεση',
|
||||
'system_notice.release_notes.promise_lead': 'Το TREK μένει δωρεάν, για πάντα.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'Κάθε λειτουργία, κάθε ενημέρωση, για όλους. Καμία έκδοση επί πληρωμή, καμία συνδρομή, καμία παγίδα.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'Και τότε το ανοίξατε. Μέσα σε λίγους μήνες γίνατε χιλιάδες: αστέρια, αναφορές σφαλμάτων, μεταφράσεις σε γλώσσες που δεν μιλάω, pull requests από ανθρώπους που δεν έχω γνωρίσει ποτέ. Ακόμα ανοίγω το αποθετήριο πρώτο πράγμα κάθε πρωί, και ακόμα δεν μου φαίνεται εντελώς αληθινό.',
|
||||
'system_notice.release_notes.note_closing': 'Σας ευχαριστώ που είστε εδώ. Φιλικά, Maurice.',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'Το TREK είναι δωρεάν και θα είναι πάντα, όμως οι servers, τα domains και τα πολλά ξενύχτια δεν είναι.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'Αν έχει κερδίσει μια θέση στα ταξίδια σας, κεράστε με έναν καφέ και βοηθήστε να έρθει η επόμενη έκδοση.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Στηρίξτε στο Ko-fi',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -54,40 +54,39 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.v3014_whitespace_collision.title': 'Szükséges beavatkozás: felhasználói fiókütközés',
|
||||
'system_notice.v3014_whitespace_collision.body':
|
||||
'A 3.0.14-es frissítés egy vagy több felhasználónév- vagy e-mail-ütközést észlelt, amelyeket a tárolt értékek elején vagy végén lévő szóközök okoztak. Az érintett fiókok automatikusan át lettek nevezve. Ellenőrizze a szervernaplókat a **[migration] WHITESPACE COLLISION** kezdetű soroknál a felülvizsgálatot igénylő fiókok azonosításához.',
|
||||
'system_notice.release_400.eyebrow': 'Frissítés telepítve',
|
||||
'system_notice.release_400.tag': 'Kiadás',
|
||||
'system_notice.release_400.headline': 'A TREK eddigi legnagyobb kiadása.',
|
||||
'system_notice.release_400.intro':
|
||||
'A TREK kap egy telefont és egy könyvet. Ezt tizenkilencen írták — és nagyjából százötven bejelentett hiba ment vele.',
|
||||
'system_notice.release_400.feature_mobile_title': 'A TREK mobilon',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'Minden 768px alatt már saját felület — üveg dokk, saját panelek, saját utazástervező. Nyisd meg a TREK-et a telefonodon.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'A Journey PDF fotókönyv-tervezővé vált. Megszerkeszti a könyvet, ha kéred, aztán félreáll.',
|
||||
'system_notice.release_400.feature_vacay_title': 'A Vacay megtanulja a többit',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Fél napok, csúsztatott és rugalmas napok, iskolai szünetek a naptárban — és szabadságév, aminek nem kell januárban kezdődnie.',
|
||||
'system_notice.release_400.feature_places_title': 'Helyek megmutatkoznak, fájlok költöznek',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'Képek és leírás maguktól kitöltődnek, mielőtt mentenél egy helyet. A feltöltéseidnek pedig már nem kell azon a lemezen lakniuk, amin a TREK fut.',
|
||||
'system_notice.release_400.footnote':
|
||||
'És ez négy közülük. A 4.0.0 több száz további változást hoz, a Collections-től és az Atlastól az egész alatta futó szerverig.',
|
||||
'system_notice.release_400.note_eyebrow': 'Egy szó a fejlesztőtől',
|
||||
'system_notice.release_400.note_title': 'Köszönöm, hogy a TREK-et használod.',
|
||||
'system_notice.release_400.note_body':
|
||||
'A TREK egy kis eszközként indult a saját utazásaimhoz, a szabadidőmben írva. Ma is az: esték, hétvégék, a teljes állás melletti órák.\n\nEgy ideig csak én voltam. Már nem — ezt a kiadást tizenkilencen szállították, és több ezren érkeztetek csillagokkal, issue-kkal, fordításokkal és pull requestekkel. Mindegyikért hálás vagyok.',
|
||||
'system_notice.release_400.promise_label': 'Az ígéret',
|
||||
'system_notice.release_400.promise_text':
|
||||
'A TREK nyílt forráskódú oldala ingyenes marad, örökre. Nincsenek fizetős csomagok, nincsenek előfizetések, nincs átverés. Ígérem.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'A 4.0.0 heteknyi késő éjszakába került — egy telefonos felület, egy könyvtervező, egy szerverköltözés, java része éjfél és kettő között írva. Nem panasz: szeretem építeni. Csak az őszinte válasz arra, hogyan születik ekkora kiadás egy szabadidős projektből.',
|
||||
'system_notice.release_400.note_closing': 'Köszönöm, hogy itt vagy.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'A támogatás tartja életben — szerverek, domainek, és a késő éjszakák, amikből ilyen kiadások lesznek. Ha a TREK ér neked valamit, egy kávé a legközvetlenebb módja, hogy tovább menjen.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Támogass a Ko-fi-n',
|
||||
'system_notice.release_notes.eyebrow': 'Frissítés telepítve',
|
||||
'system_notice.release_notes.headline': 'Három dolog, amit a TREK mostantól magától csinál.',
|
||||
'system_notice.release_notes.intro':
|
||||
'Saját hely-API, elejétől a végéig megtervezett autós utak és a helyelőzményeid újra a saját kezedben.',
|
||||
'system_notice.release_notes.features_label': 'A fő újdonságok',
|
||||
'system_notice.release_notes.features_aside': 'És ez még nem minden',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'Az első nyílt forráskódú utazástervező, amely saját hely-API-t üzemeltet. 73,6 millió hely, havonta újraépítve. Nincs kulcs, nincs kvóta.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Autós út bővítmény',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'Az Autós út mód magát a vezetést is megtervezi: az útvonalat, a távolságot, a vezetési időt és a megállókat. Ez egy bővítmény, amely addig ki van kapcsolva, amíg egy rendszergazda be nem kapcsolja.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Dawarich-integráció',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'A Google Timeline self-hosted megfelelője, mostantól a TREK-ben is olvasható. A TREK olvas, és csak olvas. Soha semmit nem ír vissza.',
|
||||
'system_notice.release_notes.footnote': 'Plusz rengeteg kisebb változás a TREK többi részében.',
|
||||
'system_notice.release_notes.notes_label': 'Kiadási jegyzetek',
|
||||
'system_notice.release_notes.note_eyebrow': 'Egy szó a fejlesztőtől',
|
||||
'system_notice.release_notes.note_title': 'Miattad építem tovább a TREK-et.',
|
||||
'system_notice.release_notes.note_body':
|
||||
'A TREK egy kis eszközként indult a saját utazásaimhoz, munka után írtam, mert jobban szerettem volna megtervezni őket. Azóta igazából folyamatosan nő. Szinte mindent, amit használsz, késő éjjel, hétvégén, vonaton, egy teljes állás mellett építettem, és sok olyan este volt, amikor csendben azon tűnődtem, megnyitja-e egyáltalán valaki valaha.',
|
||||
'system_notice.release_notes.promise_label': 'Az ígéret',
|
||||
'system_notice.release_notes.promise_lead': 'A TREK ingyenes marad, örökre.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'Minden funkció, minden frissítés, mindenkinek. Nincsenek fizetős csomagok, nincsenek előfizetések, nincs átverés.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'Aztán megnyitottátok. Néhány hónap alatt több ezren lettetek: csillagok, hibajelentések, fordítások olyan nyelvekre, amelyeket nem beszélek, pull requestek olyanoktól, akikkel sosem találkoztam. Még mindig a repóval kezdem minden reggelt, és még mindig nem egészen tűnik valóságosnak.',
|
||||
'system_notice.release_notes.note_closing': 'Köszönöm, hogy itt vagy. Maurice',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'A TREK ingyenes, és mindig az is marad, de a szerverek, a domainek és a sok késő éjszaka nem azok.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'Ha kiérdemelt egy helyet az utazásaid között, hívj meg egy kávéra, és segíts, hogy jöhessen a következő kiadás.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Támogass a Ko-fi-n',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -54,40 +54,39 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.v3014_whitespace_collision.title': 'Tindakan diperlukan: konflik akun pengguna',
|
||||
'system_notice.v3014_whitespace_collision.body':
|
||||
'Pembaruan 3.0.14 mendeteksi satu atau lebih konflik nama pengguna atau email yang disebabkan oleh spasi di awal atau akhir nilai yang tersimpan. Akun yang terpengaruh telah diganti nama secara otomatis. Periksa log server untuk baris yang dimulai dengan **[migration] WHITESPACE COLLISION** guna mengidentifikasi akun mana yang perlu ditinjau.',
|
||||
'system_notice.release_400.eyebrow': 'Pembaruan terpasang',
|
||||
'system_notice.release_400.tag': 'Rilis',
|
||||
'system_notice.release_400.headline': 'Rilis terbesar yang pernah ada di TREK.',
|
||||
'system_notice.release_400.intro':
|
||||
'TREK kini punya ponsel, dan sebuah buku. Sembilan belas orang menulis rilis ini — dan sekitar seratus lima puluh laporan bug ikut diperbaiki.',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK kini mobile',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'Semua di bawah 768px kini antarmuka tersendiri — dock kaca, sheet sendiri, perencana perjalanan sendiri. Buka TREK di ponsel Anda.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'PDF Journey berubah jadi perancang buku foto. Ia menata bukunya saat Anda minta, lalu menyingkir.',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay belajar sisanya',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Setengah hari, hari pengganti dan fleksibel, libur sekolah di kalender — dan tahun cuti yang tak harus mulai Januari.',
|
||||
'system_notice.release_400.feature_places_title': 'Tempat tampil sendiri, file pindah keluar',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'Gambar dan deskripsi terisi sendiri sebelum Anda menyimpan tempat. Dan unggahan Anda tak harus lagi tinggal di disk tempat TREK berjalan.',
|
||||
'system_notice.release_400.footnote':
|
||||
'Dan ini baru empat di antaranya. 4.0.0 membawa beberapa ratus perubahan lain, dari Collections dan Atlas sampai seluruh server di baliknya.',
|
||||
'system_notice.release_400.note_eyebrow': 'Catatan dari maintainer',
|
||||
'system_notice.release_400.note_title': 'Terima kasih telah memakai TREK.',
|
||||
'system_notice.release_400.note_body':
|
||||
'TREK dimulai sebagai alat kecil untuk perjalanan saya sendiri, ditulis di waktu luang. Sampai sekarang masih begitu: malam hari, akhir pekan, jam-jam di sela pekerjaan penuh waktu.\n\nDulu hanya saya sendiri. Sekarang tidak lagi — sembilan belas orang merilis versi ini, dan ribuan dari kalian datang dengan bintang, issue, terjemahan dan pull request. Saya bersyukur atas setiap bagiannya.',
|
||||
'system_notice.release_400.promise_label': 'Janjinya',
|
||||
'system_notice.release_400.promise_text':
|
||||
'Sisi open source TREK tetap gratis, selamanya. Tanpa paket berbayar, tanpa langganan, tanpa syarat tersembunyi. Saya janji.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'4.0.0 menghabiskan berminggu-minggu malam larut — aplikasi ponsel, perancang buku, migrasi server, sebagian besar ditulis antara pukul dua belas dan dua. Bukan keluhan: saya senang membangun ini. Ini cuma jawaban jujur bagaimana rilis sebesar ini keluar dari proyek waktu luang.',
|
||||
'system_notice.release_400.note_closing': 'Terima kasih telah berada di sini.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'Dukungan itulah yang membuat semua ini berjalan — server, domain, dan malam-malam larut yang berubah jadi rilis seperti ini. Jika TREK berarti bagimu, secangkir kopi adalah cara paling langsung untuk menjaganya tetap jalan.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Dukung di Ko-fi',
|
||||
'system_notice.release_notes.eyebrow': 'Pembaruan terpasang',
|
||||
'system_notice.release_notes.headline': 'Tiga hal yang kini dikerjakan TREK sendiri.',
|
||||
'system_notice.release_notes.intro':
|
||||
'API tempat miliknya sendiri, perjalanan darat yang direncanakan dari awal sampai akhir, dan riwayat lokasi yang kembali ke tangan Anda.',
|
||||
'system_notice.release_notes.features_label': 'Sorotan utama',
|
||||
'system_notice.release_notes.features_aside': 'Masih banyak lagi',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'Perencana perjalanan open source pertama yang menjalankan API tempatnya sendiri. 73,6 juta tempat, dibangun ulang setiap bulan. Tanpa kunci API, tanpa kuota.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Addon Perjalanan Darat',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'Mode perjalanan darat ikut merencanakan perjalanan berkendaranya: rute, jarak, lama berkendara, dan perhentiannya. Ini sebuah addon, nonaktif sampai admin mengaktifkannya.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Integrasi Dawarich',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'Alternatif self-hosted untuk Google Timeline, kini bisa dibaca langsung di TREK. TREK hanya membaca, tidak lebih. Tidak ada satu pun yang ditulis balik.',
|
||||
'system_notice.release_notes.footnote': 'Ditambah deretan panjang perubahan kecil di bagian TREK lainnya.',
|
||||
'system_notice.release_notes.notes_label': 'Catatan rilis',
|
||||
'system_notice.release_notes.note_eyebrow': 'Catatan dari maintainer',
|
||||
'system_notice.release_notes.note_title': 'Kalianlah alasan saya terus membangun TREK.',
|
||||
'system_notice.release_notes.note_body':
|
||||
'TREK dimulai sebagai alat kecil untuk perjalanan saya sendiri, saya tulis sepulang kerja karena ingin cara yang lebih baik untuk merencanakannya. Sejak itu ia tidak pernah benar-benar berhenti tumbuh. Hampir semua yang kalian pakai dibangun larut malam, di akhir pekan, di kereta, di samping pekerjaan penuh waktu, dan tak sedikit malam saya diam-diam bertanya-tanya apakah akan ada orang di luar sana yang membukanya.',
|
||||
'system_notice.release_notes.promise_label': 'Janjinya',
|
||||
'system_notice.release_notes.promise_lead': 'TREK tetap gratis, selamanya.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'Setiap fitur, setiap pembaruan, untuk semua orang. Tanpa paket berbayar, tanpa langganan, tanpa syarat tersembunyi.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'Lalu kalian datang. Dalam beberapa bulan saja jumlah kalian sudah ribuan: bintang, laporan bug, terjemahan ke bahasa yang tidak saya kuasai, pull request dari orang-orang yang belum pernah saya temui. Sampai sekarang, hal pertama yang saya lakukan setiap pagi masih membuka repositori, dan rasanya masih belum sepenuhnya nyata.',
|
||||
'system_notice.release_notes.note_closing': 'Terima kasih telah berada di sini. Salam hangat, Maurice.',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'TREK gratis dan akan selalu begitu, tetapi server, domain, dan begitu banyak malam larut tidaklah gratis.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'Jika TREK sudah mendapat tempat dalam perjalananmu, traktir saya secangkir kopi dan bantu rilis berikutnya terus hadir.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Dukung di Ko-fi',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -54,40 +54,39 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.v3014_whitespace_collision.title': 'Azione richiesta: conflitto di account utente',
|
||||
'system_notice.v3014_whitespace_collision.body':
|
||||
"L'aggiornamento 3.0.14 ha rilevato uno o più conflitti di nome utente o e-mail causati da spazi iniziali o finali nei valori memorizzati. Gli account interessati sono stati rinominati automaticamente. Controlla i log del server per le righe che iniziano con **[migration] WHITESPACE COLLISION** per identificare quali account richiedono revisione.",
|
||||
'system_notice.release_400.eyebrow': 'Aggiornato',
|
||||
'system_notice.release_400.tag': 'Versione',
|
||||
'system_notice.release_400.headline': 'La versione più grande di sempre di TREK.',
|
||||
'system_notice.release_400.intro':
|
||||
"TREK riceve un telefono, e un libro. Questa l'hanno scritta in diciannove — e con lei se ne sono andati circa centocinquanta bug segnalati.",
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK diventa mobile',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
"Tutto sotto i 768px ora è un'interfaccia a sé — una dock in vetro, i suoi pannelli, il suo pianificatore di viaggi. Apri TREK dal telefono.",
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'Il PDF di Journey è diventato un editor di libri fotografici. Impagina il libro quando glielo chiedi, poi si toglie di mezzo.',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay impara il resto',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Mezze giornate, recuperi e giorni flessibili, vacanze scolastiche nel calendario — e un anno di ferie che non deve iniziare a gennaio.',
|
||||
'system_notice.release_400.feature_places_title': 'I luoghi si mostrano, i file traslocano',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'Immagini e descrizione si compilano da sole prima che tu salvi un luogo. E i tuoi caricamenti non devono più stare sul disco dove gira TREK.',
|
||||
'system_notice.release_400.footnote':
|
||||
'E queste sono quattro. La 4.0.0 porta diverse centinaia di altre modifiche, da Collections e Atlas fino a tutto il server sotto.',
|
||||
'system_notice.release_400.note_eyebrow': 'Una nota dal maintainer',
|
||||
'system_notice.release_400.note_title': 'Grazie per usare TREK.',
|
||||
'system_notice.release_400.note_body':
|
||||
"TREK è nato come un piccolo strumento per i miei viaggi, scritto nel tempo libero. Lo è ancora: sere, weekend, le ore accanto a un lavoro a tempo pieno.\n\nPer un po' sono stato solo io. Non più — questa versione l'hanno portata in diciannove, e migliaia di voi sono arrivati con stelle, issue, traduzioni e pull request. Sono grato per ogni parte di tutto questo.",
|
||||
'system_notice.release_400.promise_label': 'La promessa',
|
||||
'system_notice.release_400.promise_text':
|
||||
'La parte open source di TREK resta gratuita, per sempre. Nessun piano a pagamento, nessun abbonamento, nessuna fregatura. Promesso.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
"La 4.0.0 è costata settimane di notti tarde — un'app per il telefono, un editor di libri, una migrazione del server, quasi tutto scritto tra mezzanotte e le due. Non è una lamentela: mi piace costruirlo. È solo la risposta onesta a come una versione così grande esca da un progetto del tempo libero.",
|
||||
'system_notice.release_400.note_closing': 'Grazie per essere qui.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'Il sostegno è ciò che tiene in piedi tutto questo — server, domini e le notti tarde che diventano versioni come questa. Se TREK vale qualcosa per te, un caffè è il modo più diretto per farlo continuare.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Supporta su Ko-fi',
|
||||
'system_notice.release_notes.eyebrow': 'Aggiornato',
|
||||
'system_notice.release_notes.headline': 'Tre cose che TREK ora fa da solo.',
|
||||
'system_notice.release_notes.intro':
|
||||
"Un'API dei luoghi tutta sua, viaggi su strada pianificati dall'inizio alla fine e la cronologia delle tue posizioni di nuovo nelle tue mani.",
|
||||
'system_notice.release_notes.features_label': 'I protagonisti',
|
||||
'system_notice.release_notes.features_aside': 'E non è tutto',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'Il primo pianificatore di viaggi open source che ospita una propria API dei luoghi. 73,6 milioni di luoghi, ricostruiti ogni mese. Nessuna chiave, nessun limite.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Addon Viaggio su strada',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'La modalità viaggio su strada pianifica il tragitto vero e proprio: il percorso, la distanza, le ore di guida e le soste. È un componente aggiuntivo, disattivato finché un admin non lo attiva.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Integrazione Dawarich',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
"L'alternativa self-hosted a Google Timeline, ora consultabile dentro TREK. TREK legge, e si limita a leggere. Non scrive mai nulla indietro.",
|
||||
'system_notice.release_notes.footnote': 'E in più una lunga lista di piccole modifiche in tutto il resto di TREK.',
|
||||
'system_notice.release_notes.notes_label': 'Note di rilascio',
|
||||
'system_notice.release_notes.note_eyebrow': 'Una nota dal maintainer',
|
||||
'system_notice.release_notes.note_title': 'Siete voi il motivo per cui continuo a sviluppare TREK.',
|
||||
'system_notice.release_notes.note_body':
|
||||
'TREK è nato come un piccolo strumento per i miei viaggi, scritto dopo il lavoro perché volevo un modo migliore per pianificarli. Non ha mai davvero smesso di crescere. Quasi tutto ciò che usate è stato costruito a tarda notte, nei weekend, in treno, accanto a un lavoro a tempo pieno, e ci sono state tante sere in cui mi chiedevo in silenzio se qualcuno là fuori lo avrebbe mai aperto.',
|
||||
'system_notice.release_notes.promise_label': 'La promessa',
|
||||
'system_notice.release_notes.promise_lead': 'TREK resta gratuito, per sempre.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'Ogni funzionalità, ogni aggiornamento, per tutti. Nessun piano a pagamento, nessun abbonamento, nessuna fregatura.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
"E poi l'avete aperto. In pochi mesi eravate migliaia: stelle, segnalazioni di bug, traduzioni in lingue che non parlo, pull request da persone che non ho mai incontrato. Ogni mattina la prima cosa che faccio è ancora controllare il repository, e ancora non mi sembra del tutto vero.",
|
||||
'system_notice.release_notes.note_closing': 'Grazie per essere qui. Un saluto da Maurice.',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'TREK è gratuito e lo sarà sempre, ma server, domini e tante notti insonni non lo sono.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'Se TREK si è guadagnato un posto nei tuoi viaggi, offrimi un caffè e aiutami a far arrivare la prossima versione.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Supporta su Ko-fi',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -52,40 +52,39 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.pager.counter': '{current} / {total}',
|
||||
'system_notice.pager.goto': '通知{n}へ',
|
||||
'system_notice.pager.position': '{total}件中{current}件目',
|
||||
'system_notice.release_400.eyebrow': 'アップデート完了',
|
||||
'system_notice.release_400.tag': 'リリース',
|
||||
'system_notice.release_400.headline': 'TREK史上、最大のリリースです。',
|
||||
'system_notice.release_400.intro':
|
||||
'TREKにスマホと、本が加わりました。19人で書き上げ、報告されていたバグ約150件も一緒に片づきました。',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREKがモバイルへ',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'768px未満は専用のインターフェースです。ガラス調のドック、専用のシート、専用の旅行プランナー。スマホでTREKを開いてください。',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'JourneyのPDFがフォトブックのデザイナーになりました。頼めばレイアウトを組み、あとは邪魔をしません。',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacayが残りを覚える',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'半休、代休とフレックス、カレンダーに並ぶ学校の休暇。そして1月始まりでなくてもいい休暇年度。',
|
||||
'system_notice.release_400.feature_places_title': '場所は自ら名乗り、ファイルは外へ',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'場所を保存する前に、写真と説明がひとりでに埋まります。アップロードしたファイルも、TREKが動くディスクに置かなくてよくなりました。',
|
||||
'system_notice.release_400.footnote':
|
||||
'これはそのうちの4つです。4.0.0にはCollectionsやAtlasから土台のサーバーまで、数百の変更が入っています。',
|
||||
'system_notice.release_400.note_eyebrow': '開発者より',
|
||||
'system_notice.release_400.note_title': 'TREKを使ってくれてありがとう。',
|
||||
'system_notice.release_400.note_body':
|
||||
'TREKは自分の旅のために、空いた時間で作った小さなツールとして始まりました。今もそれは変わりません。夜と週末、本業の合間の時間です。\n\nしばらくは私一人でした。もう違います。このリリースは19人で送り出し、何千もの人がスター、Issue、翻訳、プルリクエストを持って集まってくれました。そのすべてに感謝しています。',
|
||||
'system_notice.release_400.promise_label': '約束',
|
||||
'system_notice.release_400.promise_text':
|
||||
'TREKのオープンソースはずっと無料です。有料プランも、サブスクも、隠れた仕掛けもありません。約束します。',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'4.0.0には何週間もの夜なべがかかりました。スマホの画面、フォトブックのデザイナー、サーバーの移行。多くは深夜0時から2時のあいだに書きました。愚痴ではありません。作るのが好きです。この規模のリリースが片手間のプロジェクトからどう出るか、正直に答えればこうです。',
|
||||
'system_notice.release_400.note_closing': 'ここにいてくれて、ありがとう。',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'これを続けさせてくれているのは応援です。サーバー代、ドメイン代、そして今回のようなリリースになる夜なべ。TREKに価値を感じてもらえたなら、コーヒー一杯がいちばん直接的な支えになります。',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Ko-fiで応援する',
|
||||
'system_notice.release_notes.eyebrow': 'アップデート完了',
|
||||
'system_notice.release_notes.headline': 'TREKが自前でできるようになった、3つのこと。',
|
||||
'system_notice.release_notes.intro':
|
||||
'自前の場所API、出発から到着まで計画できるロードトリップ、そしてあなたの手元に戻ってくる位置情報の履歴。',
|
||||
'system_notice.release_notes.features_label': '今回の目玉',
|
||||
'system_notice.release_notes.features_aside': 'ほんの一部です',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'場所APIを自前で運用する、初めてのオープンソース旅行プランナーです。7,360万件の場所を毎月作り直しています。APIキーも利用上限もありません。',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'ロードトリップアドオン',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'ロードトリップモードは、ドライブそのものを計画します。ルート、距離、運転時間、立ち寄り先まで。アドオンなので、管理者が有効にするまではオフのままです。',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Dawarich連携',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'Google Timelineのセルフホスト版とも言えるDawarichを、TREKの中で読めるようになりました。TREKは読み取るだけで、それ以上のことはしません。書き戻すことは一切ありません。',
|
||||
'system_notice.release_notes.footnote': 'ほかにも、TREKのあちこちに細かな変更がたくさん入っています。',
|
||||
'system_notice.release_notes.notes_label': 'リリースノート',
|
||||
'system_notice.release_notes.note_eyebrow': '開発者より',
|
||||
'system_notice.release_notes.note_title': 'あなたがいるから、TREKを作り続けています。',
|
||||
'system_notice.release_notes.note_body':
|
||||
'TREKは、自分の旅のための小さなツールとして始まりました。もっといい計画の立て方が欲しくて、仕事のあとに書いたものです。それからずっと、大きくなり続けてきました。いま使っていただいている機能のほとんどは、本業のかたわら、深夜や週末、電車の中で作ったものです。こんなもの、誰かが開いてくれる日は来るのだろうか。そうひとりで考えた夜も、何度もありました。',
|
||||
'system_notice.release_notes.promise_label': '約束',
|
||||
'system_notice.release_notes.promise_lead': 'TREKは、ずっと無料です。',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'すべての機能も、すべてのアップデートも、すべての人に。有料プランも、サブスクも、隠れた仕掛けもありません。',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'そして、あなたが開いてくれました。数か月のうちに、それが何千人にもなりました。スター、バグ報告、私の話せない言語への翻訳、会ったこともない人からのプルリクエスト。今でも毎朝いちばんにリポジトリを確認していますが、まだ少し夢のように感じています。',
|
||||
'system_notice.release_notes.note_closing': 'ここにいてくれて、ありがとう。Mauriceより',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'TREKは無料で、これからもずっと無料です。でも、サーバーやドメイン、数えきれない夜なべはタダではありません。',
|
||||
'system_notice.release_notes.support_text':
|
||||
'TREKがあなたの旅に欠かせないものになっていたら、コーヒーを一杯おごってください。次のリリースを届ける力になります。',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Ko-fiで応援する',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -54,40 +54,39 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.pager.counter': '{current} / {total}',
|
||||
'system_notice.pager.goto': '{n}번 공지로 이동',
|
||||
'system_notice.pager.position': '공지 {current}/{total}',
|
||||
'system_notice.release_400.eyebrow': '업데이트 완료',
|
||||
'system_notice.release_400.tag': '릴리스',
|
||||
'system_notice.release_400.headline': 'TREK 역사상 가장 큰 릴리스입니다.',
|
||||
'system_notice.release_400.intro':
|
||||
'TREK에 휴대폰과 책이 생겼습니다. 열아홉 명이 함께 만들었고, 보고된 버그 약 150개가 함께 정리되었습니다.',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK, 모바일로',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'768px 아래는 이제 그 자체로 하나의 인터페이스입니다 — 글라스 독, 전용 시트, 전용 여행 플래너. 휴대폰에서 TREK을 열어보세요.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'Journey의 PDF가 사진 책 디자이너가 되었습니다. 부탁하면 책을 배치해 주고, 그다음엔 물러나 있습니다.',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay, 나머지까지',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'반차, 보상 휴가와 유연 근무일, 달력에 올라온 학교 방학 — 그리고 1월에 시작하지 않아도 되는 휴가 연도.',
|
||||
'system_notice.release_400.feature_places_title': '장소는 스스로 채우고, 파일은 밖으로',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'장소를 저장하기 전에 사진과 설명이 알아서 채워집니다. 그리고 업로드한 파일은 더 이상 TREK이 도는 디스크에 있지 않아도 됩니다.',
|
||||
'system_notice.release_400.footnote':
|
||||
'그리고 이건 그중 네 가지입니다. 4.0.0에는 Collections와 Atlas부터 그 아래 서버 전체까지 수백 가지 변경이 더 담겨 있습니다.',
|
||||
'system_notice.release_400.note_eyebrow': '개발자의 한마디',
|
||||
'system_notice.release_400.note_title': 'TREK을 사용해 주셔서 감사합니다.',
|
||||
'system_notice.release_400.note_body':
|
||||
'TREK은 제 여행을 위해 여가 시간에 만든 작은 도구로 시작했습니다. 지금도 그렇습니다. 저녁, 주말, 그리고 풀타임 직장 옆의 시간들.\n\n한동안은 저 혼자였습니다. 이제는 아닙니다 — 열아홉 명이 이번 릴리스를 함께 내보냈고, 수천 명이 별과 이슈, 번역과 풀 리퀘스트를 들고 찾아와 주셨습니다. 그 모든 것에 감사합니다.',
|
||||
'system_notice.release_400.promise_label': '약속',
|
||||
'system_notice.release_400.promise_text':
|
||||
'TREK의 오픈 소스 쪽은 영원히 무료입니다. 유료 등급도, 구독도, 숨겨진 조건도 없습니다. 약속드릴게요.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'4.0.0에는 늦은 밤 몇 주가 들어갔습니다 — 휴대폰 화면, 책 디자이너, 서버 마이그레이션, 대부분 자정과 새벽 두 시 사이에 썼습니다. 불평은 아닙니다. 이걸 만드는 게 좋습니다. 다만 이 정도 규모의 릴리스가 여가 프로젝트에서 어떻게 나오는지에 대한 솔직한 답입니다.',
|
||||
'system_notice.release_400.note_closing': '함께해 주셔서 감사합니다.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'이걸 계속 굴러가게 하는 건 후원입니다 — 서버와 도메인, 그리고 이런 릴리스가 되는 늦은 밤들. TREK이 여러분에게 가치가 있다면, 커피 한 잔이 이어가는 가장 직접적인 방법입니다.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Ko-fi에서 후원하기',
|
||||
'system_notice.release_notes.eyebrow': '업데이트 완료',
|
||||
'system_notice.release_notes.headline': '이제 TREK이 직접 해내는 세 가지.',
|
||||
'system_notice.release_notes.intro':
|
||||
'자체 장소 API, 처음부터 끝까지 계획하는 로드트립, 그리고 다시 여러분의 손으로 돌아온 위치 기록.',
|
||||
'system_notice.release_notes.features_label': '이번 릴리스의 주역',
|
||||
'system_notice.release_notes.features_aside': '이게 전부는 아닙니다',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'자체 장소 API를 직접 운영하는 최초의 오픈 소스 여행 플래너입니다. 7,360만 개의 장소를 매달 새로 구축합니다. 키도, 사용량 제한도 없습니다.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': '로드트립 애드온',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'로드트립 모드는 운전 자체를 계획합니다. 경로, 거리, 운전 시간, 경유지까지요. 애드온이라서 관리자가 켜기 전까지는 꺼져 있습니다.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Dawarich 연동',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'Google Timeline의 자체 호스팅 대안인 Dawarich를 이제 TREK 안에서 읽을 수 있습니다. TREK은 읽기만, 오직 읽기만 합니다. 다시 기록되는 것은 아무것도 없습니다.',
|
||||
'system_notice.release_notes.footnote': '그 밖에도 TREK 곳곳에 작은 변경이 많이 담겨 있습니다.',
|
||||
'system_notice.release_notes.notes_label': '릴리스 노트',
|
||||
'system_notice.release_notes.note_eyebrow': '개발자의 한마디',
|
||||
'system_notice.release_notes.note_title': '여러분이 있어서 TREK을 계속 만듭니다.',
|
||||
'system_notice.release_notes.note_body':
|
||||
'TREK은 제 여행을 위한 작은 도구로 시작했습니다. 여행을 더 잘 계획하고 싶어서 퇴근 후에 짬을 내 만들었습니다. 그 뒤로 사실상 한 번도 자라기를 멈춘 적이 없습니다. 여러분이 쓰는 거의 모든 기능은 풀타임 직장을 다니면서 늦은 밤에, 주말에, 기차 안에서 만들었고, 과연 누가 이걸 열어보기나 할까 조용히 생각하던 저녁도 많았습니다.',
|
||||
'system_notice.release_notes.promise_label': '약속',
|
||||
'system_notice.release_notes.promise_lead': 'TREK은 영원히 무료입니다.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'모든 기능, 모든 업데이트를 모두에게. 유료 등급도, 구독도, 숨겨진 조건도 없습니다.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'그런데 여러분이 열어주셨습니다. 몇 달 만에 수천 명이 찾아와 주셨습니다. 별, 버그 보고, 제가 할 줄 모르는 언어로 된 번역, 한 번도 만난 적 없는 분들의 풀 리퀘스트까지. 지금도 매일 아침 가장 먼저 저장소를 확인하는데, 아직도 잘 실감이 나지 않습니다.',
|
||||
'system_notice.release_notes.note_closing': '함께해 주셔서 감사합니다. Maurice 드림',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'TREK은 무료이고 앞으로도 그렇겠지만, 서버와 도메인, 수많은 늦은 밤은 무료가 아닙니다.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'TREK이 여러분의 여행에 자리를 잡았다면, 커피 한 잔으로 다음 릴리스가 계속 나올 수 있게 도와주세요.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Ko-fi에서 후원하기',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -54,41 +54,40 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.v3014_whitespace_collision.title': 'Actie vereist: gebruikersaccountconflict',
|
||||
'system_notice.v3014_whitespace_collision.body':
|
||||
'De 3.0.14-upgrade heeft één of meer conflicten in gebruikersnaam of e-mailadres gedetecteerd, veroorzaakt door spaties aan het begin of einde van opgeslagen waarden. Getroffen accounts zijn automatisch hernoemd. Controleer de serverlogboeken op regels die beginnen met **[migration] WHITESPACE COLLISION** om te achterhalen welke accounts moeten worden beoordeeld.',
|
||||
// 4.0.0-releasemodal — links de release, rechts het woord van de maintainer
|
||||
'system_notice.release_400.eyebrow': 'Update geïnstalleerd',
|
||||
'system_notice.release_400.tag': 'Release',
|
||||
'system_notice.release_400.headline': 'De grootste release die TREK ooit heeft gehad.',
|
||||
'system_notice.release_400.intro':
|
||||
"TREK krijgt een telefoon en een boek. Negentien mensen schreven hieraan mee — en zo'n honderdvijftig gemelde bugs gingen mee.",
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK wordt mobiel',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'Alles onder 768px is nu een eigen interface — een glazen dock, eigen sheets, een eigen reisplanner. Open TREK op je telefoon.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'De Journey-PDF werd een fotoboekontwerper. Hij maakt de opmaak wanneer je erom vraagt en gaat daarna uit de weg.',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay leert de rest',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Halve dagen, compensatie- en flexdagen, schoolvakanties in het raster — en een verlofjaar dat niet in januari hoeft te beginnen.',
|
||||
'system_notice.release_400.feature_places_title': 'Plaatsen tonen zichzelf, bestanden verhuizen',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
"Foto's en een beschrijving vullen zichzelf in voordat je een plaats opslaat. En je uploads hoeven niet langer op de schijf te staan waarop TREK draait.",
|
||||
'system_notice.release_400.footnote':
|
||||
'En dit zijn er vier. 4.0.0 bevat nog enkele honderden wijzigingen, van Collections en Atlas tot de hele server eronder.',
|
||||
'system_notice.release_400.note_eyebrow': 'Een woord van de maintainer',
|
||||
'system_notice.release_400.note_title': 'Bedankt voor het gebruik van TREK.',
|
||||
'system_notice.release_400.note_body':
|
||||
'TREK begon als een klein hulpmiddel voor mijn eigen reizen, geschreven in mijn vrije tijd. Dat is het nog steeds: avonden, weekenden, de uren naast een fulltime baan.\n\nEen tijdlang was ik de enige. Nu niet meer — negentien mensen maakten deze release, en duizenden van jullie kwamen erbij met sterren, issues, vertalingen en pull requests. Ik ben dankbaar voor elk stuk ervan.',
|
||||
'system_notice.release_400.promise_label': 'De belofte',
|
||||
'system_notice.release_400.promise_text':
|
||||
'De open source-kant van TREK blijft gratis, voor altijd. Geen betaalde versies, geen abonnementen, geen addertjes. Beloofd.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'4.0.0 kostte weken aan late avonden — een mobiele app, een fotoboekontwerper, een servermigratie, het meeste geschreven tussen middernacht en twee uur. Geen klacht: ik bouw dit graag. Het is gewoon het eerlijke antwoord op hoe een release van deze omvang uit een vrijetijdsproject komt.',
|
||||
'system_notice.release_400.note_closing': 'Bedankt dat je er bent.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'Steun is wat dit draaiende houdt — servers, domeinen en de late avonden die uitmonden in releases als deze. Als TREK iets voor je waard is, is een kopje koffie de meest directe manier om het door te laten gaan.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Steun op Ko-fi',
|
||||
// The release modal. One stable set of keys: each big release swaps the copy in place.
|
||||
'system_notice.release_notes.eyebrow': 'Update geïnstalleerd',
|
||||
'system_notice.release_notes.headline': 'Drie dingen die TREK nu zelf doet.',
|
||||
'system_notice.release_notes.intro':
|
||||
'Een eigen API voor plaatsen, roadtrips van begin tot eind gepland en je locatiegeschiedenis weer in eigen hand.',
|
||||
'system_notice.release_notes.features_label': 'De hoogtepunten',
|
||||
'system_notice.release_notes.features_aside': 'Lang niet alles',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'De eerste open source-reisplanner die zijn eigen API voor plaatsen host. 73,6 miljoen plaatsen, elke maand opnieuw opgebouwd. Geen sleutel, geen quotum.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Roadtrip-addon',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'De Roadtrip-modus plant de rit zelf: de route, de afstand, de rijtijd en de stops. Een addon die uit blijft tot een admin hem aanzet.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Dawarich-integratie',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'Het zelfgehoste antwoord op Google Timeline, nu rechtstreeks leesbaar in TREK. TREK leest, en alleen dat. Er wordt nooit iets teruggeschreven.',
|
||||
'system_notice.release_notes.footnote': 'En daarnaast een lange lijst kleinere wijzigingen in de rest van TREK.',
|
||||
'system_notice.release_notes.notes_label': 'Release notes',
|
||||
'system_notice.release_notes.note_eyebrow': 'Een woord van de maintainer',
|
||||
'system_notice.release_notes.note_title': 'Jij bent de reden dat ik aan TREK blijf bouwen.',
|
||||
'system_notice.release_notes.note_body':
|
||||
'TREK begon als een klein hulpmiddel voor mijn eigen reizen, geschreven na werktijd omdat ik ze beter wilde kunnen plannen. Eigenlijk is het nooit gestopt met groeien. Bijna alles wat je gebruikt, is gebouwd laat op de avond, in het weekend, in de trein, naast een fulltime baan, en op heel wat avonden vroeg ik me stilletjes af of iemand daarbuiten het ooit zou openen.',
|
||||
'system_notice.release_notes.promise_label': 'De belofte',
|
||||
'system_notice.release_notes.promise_lead': 'TREK blijft gratis, voor altijd.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'Elke functie, elke update, voor iedereen. Geen betaalde versies, geen abonnementen, geen addertjes.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'En toen kwamen jullie. Binnen een paar maanden waren jullie met duizenden: sterren, bugmeldingen, vertalingen in talen die ik niet spreek, pull requests van mensen die ik nooit heb ontmoet. Nog altijd kijk ik elke ochtend als eerste in de repository, en het voelt nog steeds niet helemaal echt.',
|
||||
'system_notice.release_notes.note_closing': 'Bedankt dat je er bent. Groetjes, Maurice.',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'TREK is gratis en blijft dat ook, maar servers, domeinen en heel wat late avonden zijn dat niet.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'Als TREK een plek in je reizen heeft verdiend, trakteer me dan op een kopje koffie en help zo de volgende release op weg.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Steun op Ko-fi',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -54,41 +54,40 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.v3014_whitespace_collision.title': 'Wymagane działanie: konflikt konta użytkownika',
|
||||
'system_notice.v3014_whitespace_collision.body':
|
||||
'Aktualizacja 3.0.14 wykryła jeden lub więcej konfliktów nazwy użytkownika lub adresu e-mail spowodowanych spacjami na początku lub końcu przechowywanych wartości. Dotknięte konta zostały automatycznie przemianowane. Sprawdź logi serwera pod kątem wierszy zaczynających się od **[migration] WHITESPACE COLLISION**, aby zidentyfikować konta wymagające przeglądu.',
|
||||
// 4.0.0 release modal — the release on the left, the note from the maintainer on the right
|
||||
'system_notice.release_400.eyebrow': 'Aktualizacja zainstalowana',
|
||||
'system_notice.release_400.tag': 'Wydanie',
|
||||
'system_notice.release_400.headline': 'Największe wydanie w historii TREK.',
|
||||
'system_notice.release_400.intro':
|
||||
'TREK dostaje telefon i książkę. To wydanie napisało dziewiętnaście osób — a poszło z nim około stu pięćdziesięciu zgłoszonych błędów.',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK na telefonie',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'Wszystko poniżej 768px ma teraz własny interfejs — szklany dok, własne panele, własny planer podróży. Otwórz TREK na telefonie.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'PDF z Journey stał się projektantem fotoksiążki. Układa książkę, kiedy go o to poprosisz, a potem schodzi z drogi.',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay uczy się reszty',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Pół dnia, dni wolne za nadgodziny i dni flex, ferie szkolne na siatce — i rok urlopowy, który nie musi zaczynać się w styczniu.',
|
||||
'system_notice.release_400.feature_places_title': 'Miejsca się pokazują, pliki wyprowadzają',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'Zdjęcia i opis uzupełniają się same, zanim zapiszesz miejsce. A Twoje pliki nie muszą już leżeć na dysku, na którym działa TREK.',
|
||||
'system_notice.release_400.footnote':
|
||||
'A to tylko cztery z nich. 4.0.0 niesie kilkaset kolejnych zmian, od Collections i Atlas po cały serwer pod spodem.',
|
||||
'system_notice.release_400.note_eyebrow': 'Słowo od autora',
|
||||
'system_notice.release_400.note_title': 'Dziękuję, że korzystasz z TREK.',
|
||||
'system_notice.release_400.note_body':
|
||||
'TREK zaczął się jako małe narzędzie na moje własne podróże, pisane po godzinach. Nadal takie jest: wieczory, weekendy, godziny obok pracy na pełny etat.\n\nPrzez jakiś czas byłem w tym sam. Już nie — to wydanie dowiozło dziewiętnaście osób, a tysiące z was przyszły z gwiazdkami, zgłoszeniami, tłumaczeniami i pull requestami. Jestem wdzięczny za każdy kawałek tego.',
|
||||
'system_notice.release_400.promise_label': 'Obietnica',
|
||||
'system_notice.release_400.promise_text':
|
||||
'Otwartoźródłowa część TREK pozostaje darmowa, na zawsze. Bez płatnych wersji, bez subskrypcji, bez haczyków. Obiecuję.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'4.0.0 kosztowało tygodnie nocnych sesji — aplikacja na telefon, projektant książek, migracja serwera, większość pisana między północą a drugą. To nie skarga: uwielbiam to budować. To po prostu szczera odpowiedź na to, jak z projektu po godzinach wychodzi wydanie tej wielkości.',
|
||||
'system_notice.release_400.note_closing': 'Dziękuję, że tu jesteś.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'Wsparcie jest tym, co to wszystko utrzymuje — serwery, domeny i nocne sesje, które zamieniają się w wydania takie jak to. Jeśli TREK jest dla Ciebie coś wart, kawa to najprostszy sposób, żeby to podtrzymać.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Wesprzyj na Ko-fi',
|
||||
// The release modal. One stable set of keys: each big release swaps the copy in place.
|
||||
'system_notice.release_notes.eyebrow': 'Aktualizacja zainstalowana',
|
||||
'system_notice.release_notes.headline': 'Trzy rzeczy, które TREK robi teraz sam.',
|
||||
'system_notice.release_notes.intro':
|
||||
'Własne API miejsc, podróże samochodowe zaplanowane od początku do końca i historia lokalizacji z powrotem w Twoich rękach.',
|
||||
'system_notice.release_notes.features_label': 'Najważniejsze nowości',
|
||||
'system_notice.release_notes.features_aside': 'To nie wszystko',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'Pierwszy planer podróży open source, który hostuje własne API miejsc. 73,6 miliona miejsc, przebudowywanych co miesiąc. Bez klucza, bez limitów.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Dodatek Podróż samochodowa',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'Tryb podróży samochodowej planuje samą jazdę: trasę, jej długość, czas jazdy i przystanki. To dodatek, wyłączony, dopóki administrator go nie włączy.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Integracja z Dawarich',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'Samodzielnie hostowana odpowiedź na Google Timeline, teraz dostępna w TREK. TREK tylko odczytuje, nic więcej. Nigdy niczego nie zapisuje z powrotem.',
|
||||
'system_notice.release_notes.footnote': 'Do tego długa lista mniejszych zmian w całej reszcie TREK.',
|
||||
'system_notice.release_notes.notes_label': 'Notatki do wydania',
|
||||
'system_notice.release_notes.note_eyebrow': 'Słowo od autora',
|
||||
'system_notice.release_notes.note_title': 'To dzięki wam wciąż rozwijam TREK.',
|
||||
'system_notice.release_notes.note_body':
|
||||
'TREK zaczął się jako małe narzędzie na moje własne podróże, pisane po pracy, bo chciałem wygodniej je planować. I tak naprawdę nigdy nie przestał rosnąć. Prawie wszystko, z czego korzystacie, powstało późno w nocy, w weekendy, w pociągach, obok pracy na pełny etat, i było wiele wieczorów, kiedy po cichu zastanawiałem się, czy ktokolwiek go kiedyś otworzy.',
|
||||
'system_notice.release_notes.promise_label': 'Obietnica',
|
||||
'system_notice.release_notes.promise_lead': 'TREK pozostanie darmowy, na zawsze.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'Każda funkcja, każda aktualizacja, dla wszystkich. Bez płatnych wersji, bez subskrypcji, bez haczyków.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'A potem go otworzyliście. W ciągu kilku miesięcy były was tysiące: gwiazdki, zgłoszenia błędów, tłumaczenia na języki, których nie znam, pull requesty od ludzi, których nigdy nie spotkałem. Wciąż każdego ranka najpierw zaglądam do repozytorium i wciąż nie do końca w to wierzę.',
|
||||
'system_notice.release_notes.note_closing': 'Dziękuję, że tu jesteście. Pozdrawiam, Maurice.',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'TREK jest darmowy i zawsze taki będzie, ale serwery, domeny i wiele zarwanych nocy już nie.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'Jeśli TREK zasłużył na miejsce w Twoich podróżach, postaw mi kawę i pomóż, żeby powstało kolejne wydanie.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Wesprzyj na Ko-fi',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -54,41 +54,40 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.v3014_whitespace_collision.title': 'Требуется действие: конфликт учётных записей',
|
||||
'system_notice.v3014_whitespace_collision.body':
|
||||
'Обновление 3.0.14 обнаружило один или несколько конфликтов имён пользователей или адресов электронной почты, вызванных ведущими или завершающими пробелами в сохранённых значениях. Затронутые учётные записи были автоматически переименованы. Проверьте логи сервера на строки, начинающиеся с **[migration] WHITESPACE COLLISION**, чтобы определить учётные записи, требующие проверки.',
|
||||
// 4.0.0 release modal — the release on the left, the note from the maintainer on the right
|
||||
'system_notice.release_400.eyebrow': 'Обновление установлено',
|
||||
'system_notice.release_400.tag': 'Релиз',
|
||||
'system_notice.release_400.headline': 'Самый большой релиз в истории TREK.',
|
||||
'system_notice.release_400.intro':
|
||||
'TREK получает телефон и книгу. Этот релиз написали девятнадцать человек — и вместе с ним закрылись около ста пятидесяти присланных багов.',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK на телефоне',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'Всё, что уже 768px, теперь отдельный интерфейс — стеклянный док, свои шторки, свой планировщик поездок. Откройте TREK на телефоне.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'PDF из Journey превратился в конструктор фотокниги. Он собирает книгу, когда вы попросите, и дальше не мешает.',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay освоил остальное',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Полдня, отгулы и гибкие дни, школьные каникулы в сетке — и отпускной год, который не обязан начинаться в январе.',
|
||||
'system_notice.release_400.feature_places_title': 'Места показывают себя, файлы съезжают',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'Фото и описание подставляются сами ещё до того, как вы сохраните место. А загруженные файлы больше не обязаны лежать на диске, где работает TREK.',
|
||||
'system_notice.release_400.footnote':
|
||||
'И это только четыре из них. В 4.0.0 ещё несколько сотен изменений — от Collections и Atlas до всего сервера под ними.',
|
||||
'system_notice.release_400.note_eyebrow': 'Слово от мейнтейнера',
|
||||
'system_notice.release_400.note_title': 'Спасибо, что пользуетесь TREK.',
|
||||
'system_notice.release_400.note_body':
|
||||
'TREK начинался как маленький инструмент для моих собственных поездок, написанный в свободное время. Таким он и остался: вечера, выходные, часы рядом с основной работой.\n\nКакое-то время я был один. Уже нет — этот релиз выпустили девятнадцать человек, а тысячи из вас пришли со звёздами, issue, переводами и пул-реквестами. Я благодарен за каждую часть этого.',
|
||||
'system_notice.release_400.promise_label': 'Обещание',
|
||||
'system_notice.release_400.promise_text':
|
||||
'Открытая часть TREK остаётся бесплатной навсегда. Никаких платных тарифов, никаких подписок, никаких подвохов. Обещаю.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'4.0.0 стоил недель поздних ночей — приложение для телефона, конструктор книги, миграция сервера, и почти всё это написано между полуночью и двумя. Это не жалоба: мне нравится это делать. Просто честный ответ на то, как релиз такого размера выходит из проекта в свободное время.',
|
||||
'system_notice.release_400.note_closing': 'Спасибо, что вы здесь.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'Поддержка — это то, на чём всё держится: серверы, домены и те поздние ночи, из которых получаются такие релизы. Если TREK для вас чего-то стоит, кофе — самый прямой способ помочь.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Поддержать на Ko-fi',
|
||||
// The release modal. One stable set of keys: each big release swaps the copy in place.
|
||||
'system_notice.release_notes.eyebrow': 'Обновление установлено',
|
||||
'system_notice.release_notes.headline': 'Три вещи, которые TREK теперь делает сам.',
|
||||
'system_notice.release_notes.intro':
|
||||
'Собственный API мест, автопутешествия, продуманные от старта до финиша, и история перемещений, которая снова принадлежит вам.',
|
||||
'system_notice.release_notes.features_label': 'Главные новинки',
|
||||
'system_notice.release_notes.features_aside': 'И это далеко не всё',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'Первый планировщик путешествий с открытым исходным кодом, у которого есть собственный API мест. 73,6 миллиона мест, база заново собирается каждый месяц. Никаких ключей, никаких квот.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Дополнение «Автопутешествие»',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'Режим автопутешествия планирует саму дорогу: маршрут, расстояние, часы за рулём и остановки. Это дополнение, и оно выключено, пока администратор его не включит.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Интеграция с Dawarich',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'Альтернатива Google Timeline на вашем собственном сервере, и теперь её данные видны прямо в TREK. TREK читает, и только читает. Обратно не записывается ничего и никогда.',
|
||||
'system_notice.release_notes.footnote': 'Плюс длинный список небольших изменений во всём остальном TREK.',
|
||||
'system_notice.release_notes.notes_label': 'Заметки к релизу',
|
||||
'system_notice.release_notes.note_eyebrow': 'Слово от мейнтейнера',
|
||||
'system_notice.release_notes.note_title': 'Именно ради вас я продолжаю развивать TREK.',
|
||||
'system_notice.release_notes.note_body':
|
||||
'TREK начинался как маленький инструмент для моих собственных поездок: я писал его после работы, потому что хотел планировать их удобнее. С тех пор он, по сути, так и не перестал расти. Почти всё, чем вы пользуетесь, создано поздно ночью, по выходным, в поездах, параллельно с основной работой, и было немало вечеров, когда я тихо сомневался, откроет ли его вообще хоть кто-нибудь.',
|
||||
'system_notice.release_notes.promise_label': 'Обещание',
|
||||
'system_notice.release_notes.promise_lead': 'TREK остаётся бесплатным навсегда.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'Все функции и все обновления, для всех. Никаких платных тарифов, никаких подписок, никаких подвохов.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'А потом его открыли вы. За несколько месяцев вас стали тысячи: звёзды, отчёты об ошибках, переводы на языки, которыми я не владею, пул-реквесты от людей, с которыми я ни разу не встречался. Я до сих пор каждое утро первым делом заглядываю в репозиторий, и мне всё ещё не до конца верится, что это происходит.',
|
||||
'system_notice.release_notes.note_closing': 'Спасибо, что вы здесь. Ваш Maurice.',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'TREK бесплатен и таким останется, а вот серверы, домены и бесконечные поздние вечера бесплатными не бывают.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'Если TREK заслужил место в ваших поездках, угостите меня кофе и помогите выпустить следующий релиз.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Поддержать на Ko-fi',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -54,41 +54,40 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.pager.counter': '{current} / {total}',
|
||||
'system_notice.pager.goto': 'Gå till meddelandet {n}',
|
||||
'system_notice.pager.position': 'Meddlenade {current} av {total}',
|
||||
// 4.0.0 release modal — the release on the left, the note from the maintainer on the right
|
||||
'system_notice.release_400.eyebrow': 'Uppdatering klar',
|
||||
'system_notice.release_400.tag': 'Utgåva',
|
||||
'system_notice.release_400.headline': 'Den största utgåvan TREK har haft.',
|
||||
'system_notice.release_400.intro':
|
||||
'TREK får en telefon, och en bok. Nitton personer skrev den här — och ungefär hundrafemtio rapporterade fel följde med.',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK blir mobilt',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'Allt under 768px är ett eget gränssnitt nu — en dock i glas, egna paneler, en egen resplanerare. Öppna TREK i telefonen.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'Journey-PDF:en blev en fotoboksdesigner. Den lägger ut boken när du ber om det, och håller sig sedan undan.',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay lär sig resten',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Halvdagar, komp- och flexdagar, skollov i rutnätet — och ett semesterår som inte måste börja i januari.',
|
||||
'system_notice.release_400.feature_places_title': 'Platser visar sig, filer flyttar ut',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'Bilder och en beskrivning fyller i sig själva innan du sparar en plats. Och dina uppladdningar behöver inte längre ligga på disken TREK kör på.',
|
||||
'system_notice.release_400.footnote':
|
||||
'Och det här är fyra av dem. 4.0.0 innehåller flera hundra ytterligare ändringar, från Collections och Atlas till hela servern under.',
|
||||
'system_notice.release_400.note_eyebrow': 'Ett ord från utvecklaren',
|
||||
'system_notice.release_400.note_title': 'Tack för att du använder TREK.',
|
||||
'system_notice.release_400.note_body':
|
||||
'TREK började som ett litet verktyg för mina egna resor, skrivet på fritiden. Det är det fortfarande: kvällar, helger, timmarna vid sidan av ett heltidsjobb.\n\nEtt tag var det bara jag. Inte längre — nitton personer levererade den här utgåvan, och tusentals av er kom med stjärnor, ärenden, översättningar och pull requests. Jag är tacksam för varenda del av det.',
|
||||
'system_notice.release_400.promise_label': 'Löftet',
|
||||
'system_notice.release_400.promise_text':
|
||||
'Den öppna delen av TREK är gratis, för alltid. Inga betalnivåer, inga prenumerationer, inga förbehåll. Lovat.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'4.0.0 tog veckor av sena nätter — en mobilapp, en fotoboksdesigner, en servermigrering, det mesta skrivet mellan midnatt och två. Inget gnäll: jag älskar att bygga det här. Det är bara det ärliga svaret på hur en utgåva av den här storleken kommer ur ett fritidsprojekt.',
|
||||
'system_notice.release_400.note_closing': 'Tack för att du är här.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'Stödet är det som håller igång det här — servrar, domäner och de sena nätter som blir till utgåvor som den här. Om TREK är värt något för dig är en kaffe det mest direkta sättet att hålla det vid liv.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Stöd på Ko-fi',
|
||||
// The release modal. One stable set of keys: each big release swaps the copy in place.
|
||||
'system_notice.release_notes.eyebrow': 'Uppdatering klar',
|
||||
'system_notice.release_notes.headline': 'Tre saker som TREK nu klarar på egen hand.',
|
||||
'system_notice.release_notes.intro':
|
||||
'Ett eget API för platser, bilresor planerade från start till mål och din platshistorik tillbaka i dina händer.',
|
||||
'system_notice.release_notes.features_label': 'Höjdpunkterna',
|
||||
'system_notice.release_notes.features_aside': 'Långt ifrån allt',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'Den första resplaneraren med öppen källkod som driver sitt eget API för platser. 73,6 miljoner platser som byggs om varje månad. Ingen nyckel, ingen kvot.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Tillägget Bilresa',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'Bilreseläget planerar själva körningen: rutten, sträckan, körtiden och stoppen. Ett tillägg som är avstängt tills en administratör slår på det.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Dawarich-integration',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'Det självhostade svaret på Google Timeline, nu läsbart direkt i TREK. TREK läser, och bara läser. Ingenting skrivs någonsin tillbaka.',
|
||||
'system_notice.release_notes.footnote': 'Dessutom en lång rad mindre ändringar i resten av TREK.',
|
||||
'system_notice.release_notes.notes_label': 'Versionsnyheter',
|
||||
'system_notice.release_notes.note_eyebrow': 'Ett ord från utvecklaren',
|
||||
'system_notice.release_notes.note_title': 'Du är anledningen till att jag fortsätter bygga TREK.',
|
||||
'system_notice.release_notes.note_body':
|
||||
'TREK började som ett litet verktyg för mina egna resor, skrivet efter jobbet för att jag ville ha ett bättre sätt att planera dem. Det har egentligen aldrig slutat växa. Nästan allt du använder byggdes sent på nätterna, på helger, på tåg, vid sidan av ett heltidsjobb, och många kvällar undrade jag tyst för mig själv om någon där ute någonsin skulle öppna det.',
|
||||
'system_notice.release_notes.promise_label': 'Löftet',
|
||||
'system_notice.release_notes.promise_lead': 'TREK förblir gratis, för alltid.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'Varje funktion, varje uppdatering, för alla. Inga betalnivåer, inga prenumerationer, inga förbehåll.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'Och sedan gjorde ni det. Inom några månader var ni tusentals: stjärnor, felrapporter, översättningar till språk jag inte talar, pull requests från människor jag aldrig har träffat. Jag kollar fortfarande repot varje morgon innan jag gör något annat, och det känns ännu inte riktigt verkligt.',
|
||||
'system_notice.release_notes.note_closing': 'Tack för att du är här. Hälsningar, Maurice.',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'TREK är gratis och kommer alltid att vara det, men servrar, domäner och många sena nätter är det inte.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'Om TREK har förtjänat en plats på dina resor, så bjud mig gärna på en kaffe och hjälp till att nästa utgåva blir av.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Stöd på Ko-fi',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -54,40 +54,40 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.pager.counter': '{current} / {total}',
|
||||
'system_notice.pager.goto': '{n}. bildirime git',
|
||||
'system_notice.pager.position': '{total} Bildirimden {current}.',
|
||||
'system_notice.release_400.eyebrow': 'Güncelleme yüklendi',
|
||||
'system_notice.release_400.tag': 'Sürüm',
|
||||
'system_notice.release_400.headline': "TREK'in bugüne kadarki en büyük sürümü.",
|
||||
'system_notice.release_400.intro':
|
||||
'TREK bir telefon ve bir kitap kazanıyor. Bunu on dokuz kişi yazdı — ve yaklaşık yüz elli bildirilen hata da onunla birlikte gitti.',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK mobile geçiyor',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
"768px altındaki her şey artık kendi arayüzü — cam bir dock, kendi panelleri, kendi seyahat planlayıcısı. TREK'i telefonunda aç.",
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
"Journey PDF'i bir fotoğraf kitabı tasarımcısına dönüştü. İstediğinde kitabı kendisi düzenler, sonra yoldan çekilir.",
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay gerisini öğreniyor',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Yarım günler, telafi ve esnek günler, takvimde okul tatilleri — ve ocakta başlamak zorunda olmayan bir izin yılı.',
|
||||
'system_notice.release_400.feature_places_title': 'Yerler kendini gösterir, dosyalar taşınır',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
"Bir yeri kaydetmeden önce resimler ve açıklama kendiliğinden dolar. Ve yüklemelerinin artık TREK'in çalıştığı diskte durması gerekmiyor.",
|
||||
'system_notice.release_400.footnote':
|
||||
"Ve bunlar onlardan sadece dördü. 4.0.0, Collections ve Atlas'tan alttaki sunucunun tamamına kadar birkaç yüz değişiklik daha taşıyor.",
|
||||
'system_notice.release_400.note_eyebrow': 'Geliştiriciden bir not',
|
||||
'system_notice.release_400.note_title': "TREK'i kullandığın için teşekkürler.",
|
||||
'system_notice.release_400.note_body':
|
||||
"TREK, boş zamanlarımda kendi seyahatlerim için yazdığım küçük bir araç olarak başladı. Hâlâ da öyle: akşamlar, hafta sonları, tam zamanlı bir işin yanındaki saatler.\n\nBir süre yalnızca bendim. Artık değil — bu sürümü on dokuz kişi çıkardı ve binlerceniz yıldızlarla, issue'larla, çevirilerle ve pull request'lerle geldiniz. Her biri için minnettarım.",
|
||||
'system_notice.release_400.promise_label': 'Söz',
|
||||
'system_notice.release_400.promise_text':
|
||||
"TREK'in açık kaynak tarafı sonsuza dek ücretsiz kalıyor. Ücretli paket yok, abonelik yok, gizli şart yok. Söz.",
|
||||
'system_notice.release_400.note_body_after':
|
||||
'4.0.0, haftalarca süren geç geceler demekti — bir telefon uygulaması, bir kitap tasarımcısı, bir sunucu taşıması, çoğu gece yarısı ile ikisi arasında yazıldı. Şikâyet değil: bunu geliştirmeyi seviyorum. Sadece bu büyüklükte bir sürümün boş zaman projesinden nasıl çıktığının dürüst cevabı.',
|
||||
'system_notice.release_400.note_closing': 'Burada olduğun için teşekkür ederim.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'Bunu ayakta tutan şey destek — sunucular, alan adları ve böyle sürümlere dönüşen geç geceler. TREK senin için bir şey ifade ediyorsa, bir kahve bunu sürdürmenin en doğrudan yolu.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': "Ko-fi'de Destek Ol",
|
||||
'system_notice.release_notes.eyebrow': 'Güncelleme yüklendi',
|
||||
'system_notice.release_notes.headline': "TREK'in artık kendi başına yaptığı üç şey.",
|
||||
'system_notice.release_notes.intro':
|
||||
"Kendi yer API'si, baştan sona planlanan yol gezileri ve yeniden senin elinde olan konum geçmişin.",
|
||||
'system_notice.release_notes.features_label': 'Öne çıkanlar',
|
||||
'system_notice.release_notes.features_aside': 'Hepsi bu kadar değil',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
"Kendi yer API'sini barındıran ilk açık kaynak seyahat planlayıcısı. 73,6 milyon yer, her ay yeniden oluşturuluyor. Anahtar yok, kota yok.",
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Yol gezisi eklentisi',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'Yol gezisi modu sürüşün kendisini planlar: rotayı, mesafeyi, süreyi ve durakları. Bir eklentidir ve bir yönetici açana kadar kapalı kalır.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Dawarich entegrasyonu',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
"Google Timeline'ın kendi sunucunda çalışan alternatifi, artık TREK içinden okunabiliyor. TREK okur, yalnızca okur. Geriye hiçbir zaman hiçbir şey yazılmaz.",
|
||||
'system_notice.release_notes.footnote':
|
||||
"Ayrıca TREK'in geri kalanına yayılmış, daha küçük değişikliklerden oluşan uzun bir liste var.",
|
||||
'system_notice.release_notes.notes_label': 'Sürüm notları',
|
||||
'system_notice.release_notes.note_eyebrow': 'Geliştiriciden bir not',
|
||||
'system_notice.release_notes.note_title': "TREK'i geliştirmeye devam etmemin sebebi sensin.",
|
||||
'system_notice.release_notes.note_body':
|
||||
'TREK, kendi seyahatlerim için küçük bir araç olarak başladı. Onları daha iyi planlamak istediğim için iş çıkışlarında yazıyordum. O günden beri de büyümeyi hiç tam olarak bırakmadı. Kullandığın neredeyse her şey gece geç saatlerde, hafta sonlarında, trenlerde, tam zamanlı bir işin yanında yapıldı ve birinin onu bir gün gerçekten açıp açmayacağını içten içe merak ettiğim çok akşam oldu.',
|
||||
'system_notice.release_notes.promise_label': 'Söz',
|
||||
'system_notice.release_notes.promise_lead': 'TREK sonsuza dek ücretsiz kalacak.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'Her özellik, her güncelleme, herkes için. Ücretli paket yok, abonelik yok, gizli şart yok.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
"Sonra sizler açtınız. Birkaç ay içinde sayınız binleri buldu: yıldızlar, hata bildirimleri, konuşmadığım dillere çeviriler, hiç tanışmadığım insanlardan pull request'ler. Hâlâ her sabah ilk iş repoya bakıyorum ve bu hâlâ tam olarak gerçekmiş gibi gelmiyor.",
|
||||
'system_notice.release_notes.note_closing': 'Burada olduğun için teşekkür ederim. Sevgiler, Maurice.',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'TREK ücretsiz ve hep öyle kalacak, ama sunucular, alan adları ve bir sürü geç gece ücretsiz değil.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'TREK seyahatlerinde kendine bir yer edindiyse, bana bir kahve ısmarla ve bir sonraki sürümün gelmesine yardım et.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': "Ko-fi'de Destek Ol",
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -54,41 +54,40 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.v3014_whitespace_collision.title': 'Потрібна дія: конфлікт облікового запису користувача',
|
||||
'system_notice.v3014_whitespace_collision.body':
|
||||
'Оновлення 3.0.14 виявило один або кілька конфліктів імен користувачів або електронних адрес, спричинених початковими або кінцевими пробілами в збережених облікових записах. Уражені облікові записи було автоматично перейменовано. Перевірте журнали сервера на рядки, що починаються з **[migration] WHITESPACE COLLISION**, щоб визначити, які облікові записи потребують перевірки.',
|
||||
// 4.0.0 release modal — the release on the left, the note from the maintainer on the right
|
||||
'system_notice.release_400.eyebrow': 'Оновлення встановлено',
|
||||
'system_notice.release_400.tag': 'Реліз',
|
||||
'system_notice.release_400.headline': 'Найбільший реліз в історії TREK.',
|
||||
'system_notice.release_400.intro':
|
||||
'TREK отримує телефон і книгу. Цей реліз написали дев’ятнадцять людей — і разом з ним закрилися близько ста п’ятдесяти надісланих багів.',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK на телефоні',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'Усе, що вужче за 768px, тепер окремий інтерфейс — скляний док, власні шторки, власний планувальник поїздок. Відкрийте TREK на телефоні.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'PDF із Journey став конструктором фотокниги. Він збирає книгу, коли ви попросите, і далі не заважає.',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay освоїв решту',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Півдня, відгули та гнучкі дні, шкільні канікули в сітці — і відпускний рік, який не мусить починатися в січні.',
|
||||
'system_notice.release_400.feature_places_title': 'Місця показують себе, файли з’їжджають',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'Фото й опис підставляються самі ще до того, як ви збережете місце. А завантажені файли більше не мусять лежати на диску, де працює TREK.',
|
||||
'system_notice.release_400.footnote':
|
||||
'І це лише чотири з них. У 4.0.0 ще кілька сотень змін — від Collections і Atlas до всього сервера під ними.',
|
||||
'system_notice.release_400.note_eyebrow': 'Слово від мейнтейнера',
|
||||
'system_notice.release_400.note_title': 'Дякую, що користуєтесь TREK.',
|
||||
'system_notice.release_400.note_body':
|
||||
'TREK починався як маленький інструмент для моїх власних поїздок, написаний у вільний час. Таким і залишився: вечори, вихідні, години поруч з основною роботою.\n\nЯкийсь час я був сам. Уже ні — цей реліз випустили дев’ятнадцять людей, а тисячі з вас прийшли із зірками, issue, перекладами та пул-реквестами. Я вдячний за кожну частину цього.',
|
||||
'system_notice.release_400.promise_label': 'Обіцянка',
|
||||
'system_notice.release_400.promise_text':
|
||||
'Відкрита частина TREK залишається безкоштовною назавжди. Жодних платних тарифів, жодних підписок, жодних підводних каменів. Обіцяю.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'4.0.0 коштував тижнів пізніх ночей — застосунок для телефона, конструктор книги, міграція сервера, і майже все це написано між північчю і другою. Це не скарга: мені подобається це робити. Просто чесна відповідь на те, як реліз такого розміру виходить із проєкту у вільний час.',
|
||||
'system_notice.release_400.note_closing': 'Дякую, що ви тут.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'Підтримка — це те, на чому все тримається: сервери, домени і ті пізні ночі, з яких виходять такі релізи. Якщо TREK для вас чогось вартий, кава — найпряміший спосіб допомогти.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Підтримати на Ko-fi',
|
||||
// The release modal. One stable set of keys: each big release swaps the copy in place.
|
||||
'system_notice.release_notes.eyebrow': 'Оновлення встановлено',
|
||||
'system_notice.release_notes.headline': 'Три речі, які TREK тепер робить сам.',
|
||||
'system_notice.release_notes.intro':
|
||||
'Власний API місць, автоподорожі, сплановані від початку до кінця, і ваша історія місцезнаходжень знову у ваших руках.',
|
||||
'system_notice.release_notes.features_label': 'Головні новинки',
|
||||
'system_notice.release_notes.features_aside': 'І це далеко не все',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'Перший планувальник подорожей з відкритим кодом, який має власний API місць. 73,6 мільйона місць, щомісяця зібраних наново. Без ключа, без квот.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Доповнення «Автоподорож»',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'Режим автоподорожі планує саму поїздку: маршрут, відстань, години в дорозі та зупинки. Це доповнення, і воно вимкнене, доки його не ввімкне адміністратор.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Інтеграція з Dawarich',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'Self-hosted альтернатива Google Timeline, яку тепер можна читати прямо в TREK. TREK читає, і тільки читає. Назад нічого ніколи не записується.',
|
||||
'system_notice.release_notes.footnote': 'А також довгий список дрібніших змін по всьому TREK.',
|
||||
'system_notice.release_notes.notes_label': 'Нотатки до релізу',
|
||||
'system_notice.release_notes.note_eyebrow': 'Слово від мейнтейнера',
|
||||
'system_notice.release_notes.note_title': 'Саме заради вас я далі розвиваю TREK.',
|
||||
'system_notice.release_notes.note_body':
|
||||
'TREK починався як маленький інструмент для моїх власних поїздок, який я писав після роботи, бо хотів планувати їх краще. І відтоді він, власне, не переставав рости. Майже все, чим ви користуєтесь, створено пізно вночі, на вихідних, у поїздах, поруч з основною роботою, і було чимало вечорів, коли я тихо питав себе, чи хтось узагалі колись його відкриє.',
|
||||
'system_notice.release_notes.promise_label': 'Обіцянка',
|
||||
'system_notice.release_notes.promise_lead': 'TREK залишиться безкоштовним назавжди.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'Кожна функція, кожне оновлення, для всіх. Жодних платних тарифів, жодних підписок, жодних підводних каменів.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'А потім його відкрили ви. За кілька місяців вас стали тисячі: зірки, звіти про баги, переклади мовами, якими я не володію, пул-реквести від людей, яких я ніколи не зустрічав. Я й досі щоранку насамперед заглядаю в репозиторій, і досі в це не зовсім віриться.',
|
||||
'system_notice.release_notes.note_closing': 'Дякую, що ви тут. Ваш Maurice',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'TREK безкоштовний і таким залишиться, а от сервери, домени й безліч пізніх ночей ні.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'Якщо TREK заслужив місце у ваших подорожах, пригостіть мене кавою і допоможіть наблизити наступний реліз.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Підтримати на Ko-fi',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -55,41 +55,41 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.pager.counter': '{current} / {total}',
|
||||
'system_notice.pager.goto': 'Vào thông báo {n}',
|
||||
'system_notice.pager.position': 'Thông báo {current} của {total}',
|
||||
// 4.0.0 release modal — the release on the left, the note from the maintainer on the right
|
||||
'system_notice.release_400.eyebrow': 'Đã cập nhật',
|
||||
'system_notice.release_400.tag': 'Phiên bản',
|
||||
'system_notice.release_400.headline': 'Bản phát hành lớn nhất TREK từng có.',
|
||||
'system_notice.release_400.intro':
|
||||
'TREK có điện thoại, và một cuốn sách. Mười chín người đã viết nên bản này — cùng khoảng một trăm năm mươi lỗi được báo cáo.',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK lên di động',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'Mọi thứ dưới 768px giờ là giao diện riêng — thanh dock kính, các bảng riêng, công cụ lập kế hoạch riêng. Mở TREK trên điện thoại.',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'Bản PDF của Journey đã thành một công cụ thiết kế sách ảnh. Nó tự dàn trang khi bạn yêu cầu, rồi lui ra một bên.',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay học nốt',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'Nửa ngày, ngày bù và ngày linh hoạt, kỳ nghỉ học trên lưới — và một năm phép không nhất thiết bắt đầu từ tháng Một.',
|
||||
'system_notice.release_400.feature_places_title': 'Địa điểm tự hiện ra, tệp dọn ra ngoài',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'Ảnh và mô tả tự điền vào trước khi bạn lưu một địa điểm. Và các tệp tải lên không còn phải nằm trên ổ đĩa chạy TREK nữa.',
|
||||
'system_notice.release_400.footnote':
|
||||
'Và đây mới là bốn trong số đó. 4.0.0 mang theo vài trăm thay đổi khác, từ Collections và Atlas cho tới toàn bộ máy chủ bên dưới.',
|
||||
'system_notice.release_400.note_eyebrow': 'Lời nhắn từ người bảo trì',
|
||||
'system_notice.release_400.note_title': 'Cảm ơn bạn đã sử dụng TREK.',
|
||||
'system_notice.release_400.note_body':
|
||||
'TREK bắt đầu như một công cụ nhỏ cho chuyến đi của riêng tôi, viết trong thời gian rảnh. Đến giờ vẫn vậy: buổi tối, cuối tuần, những giờ bên cạnh công việc toàn thời gian.\n\nĐã có lúc chỉ mình tôi. Giờ thì không nữa — mười chín người đã làm nên bản phát hành này, và hàng nghìn bạn đã đến với sao, báo lỗi, bản dịch và pull request. Tôi biết ơn tất cả.',
|
||||
'system_notice.release_400.promise_label': 'Lời hứa',
|
||||
'system_notice.release_400.promise_text':
|
||||
'Phần mã nguồn mở của TREK vẫn miễn phí, mãi mãi. Không tầng trả phí, không đăng ký, không ràng buộc. Tôi hứa.',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'4.0.0 tốn nhiều tuần thức khuya — một ứng dụng điện thoại, một công cụ thiết kế sách, một lần chuyển máy chủ, phần lớn viết từ nửa đêm đến hai giờ. Không phải than phiền: tôi thích làm việc này. Đó chỉ là câu trả lời thật lòng cho việc một bản cỡ này ra đời từ một dự án lúc rảnh.',
|
||||
'system_notice.release_400.note_closing': 'Cảm ơn bạn đã ở đây.',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'Sự ủng hộ là thứ giữ cho mọi thứ chạy — máy chủ, tên miền, và những đêm khuya biến thành các bản phát hành như thế này. Nếu TREK có giá trị với bạn, một ly cà phê là cách trực tiếp nhất để duy trì nó.',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': 'Hỗ trợ trên Ko-fi',
|
||||
// The release modal. One stable set of keys: each big release swaps the copy in place.
|
||||
'system_notice.release_notes.eyebrow': 'Đã cập nhật',
|
||||
'system_notice.release_notes.headline': 'Ba điều giờ đây TREK tự làm được.',
|
||||
'system_notice.release_notes.intro':
|
||||
'API địa điểm của riêng mình, chuyến đi đường bộ được lên kế hoạch trọn vẹn từ đầu đến cuối, và lịch sử vị trí trở về trong tay bạn.',
|
||||
'system_notice.release_notes.features_label': 'Những điểm nhấn',
|
||||
'system_notice.release_notes.features_aside': 'Chưa phải tất cả',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'Công cụ lập kế hoạch du lịch mã nguồn mở đầu tiên tự vận hành API địa điểm của riêng mình. 73,6 triệu địa điểm, dựng lại mỗi tháng. Không cần khóa, không giới hạn lượt dùng.',
|
||||
'system_notice.release_notes.feature_roadtrip_title': 'Tiện ích Chuyến đi đường bộ',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'Chế độ chuyến đi đường bộ tự lên kế hoạch cho cả hành trình lái xe: tuyến đường, quãng đường, số giờ lái và các điểm dừng. Đây là một tiện ích bổ sung, được tắt cho đến khi quản trị viên bật lên.',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Tích hợp Dawarich',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'Lựa chọn tự lưu trữ thay cho Google Timeline, giờ đã đọc được ngay trong TREK. TREK chỉ đọc, và chỉ đọc mà thôi. Không có gì bị ghi ngược lại.',
|
||||
'system_notice.release_notes.footnote':
|
||||
'Và còn cả một danh sách dài những thay đổi nhỏ hơn ở khắp phần còn lại của TREK.',
|
||||
'system_notice.release_notes.notes_label': 'Ghi chú phát hành',
|
||||
'system_notice.release_notes.note_eyebrow': 'Lời nhắn từ người bảo trì',
|
||||
'system_notice.release_notes.note_title': 'Bạn là lý do tôi tiếp tục xây dựng TREK.',
|
||||
'system_notice.release_notes.note_body':
|
||||
'TREK bắt đầu là một công cụ nhỏ cho những chuyến đi của riêng tôi, viết sau giờ làm vì tôi muốn có một cách lên kế hoạch tốt hơn. Từ đó đến giờ nó chưa bao giờ thật sự ngừng lớn lên. Gần như mọi thứ bạn đang dùng đều được làm vào đêm khuya, vào cuối tuần, trên tàu, bên cạnh một công việc toàn thời gian, và đã có không ít buổi tối tôi lặng lẽ tự hỏi liệu có ai ngoài kia sẽ mở nó ra không.',
|
||||
'system_notice.release_notes.promise_label': 'Lời hứa',
|
||||
'system_notice.release_notes.promise_lead': 'TREK luôn miễn phí, mãi mãi.',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'Mọi tính năng, mọi bản cập nhật, cho tất cả mọi người. Không tầng trả phí, không đăng ký, không ràng buộc.',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'Rồi các bạn đã mở nó. Chỉ trong vài tháng đã có hàng nghìn bạn: những ngôi sao, báo lỗi, bản dịch sang những ngôn ngữ tôi không biết nói, pull request từ những người tôi chưa từng gặp. Đến giờ, việc đầu tiên tôi làm mỗi sáng vẫn là mở kho mã, và cảm giác vẫn chưa hẳn là thật.',
|
||||
'system_notice.release_notes.note_closing': 'Cảm ơn bạn đã ở đây. Thân mến, Maurice.',
|
||||
'system_notice.release_notes.support_lead':
|
||||
'TREK miễn phí và sẽ luôn như vậy, nhưng máy chủ, tên miền và rất nhiều đêm thức khuya thì không.',
|
||||
'system_notice.release_notes.support_text':
|
||||
'Nếu TREK đã có một chỗ trong những chuyến đi của bạn, hãy mời tôi một ly cà phê để bản phát hành tiếp theo tiếp tục ra đời.',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': 'Hỗ trợ trên Ko-fi',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -53,40 +53,39 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.v3014_whitespace_collision.title': '需要操作:使用者帳戶衝突',
|
||||
'system_notice.v3014_whitespace_collision.body':
|
||||
'3.0.14 版本升級偵測到一個或多個由儲存帳戶中前後空白字元引發的使用者名稱或電子郵件衝突。受影響的帳戶已自動重新命名。請檢查伺服器日誌中以 **[migration] WHITESPACE COLLISION** 開頭的行,以確認哪些帳戶需要審查。',
|
||||
// 4.0.0 release modal — the release on the left, the note from the maintainer on the right
|
||||
'system_notice.release_400.eyebrow': '更新已安裝',
|
||||
'system_notice.release_400.tag': '發布',
|
||||
'system_notice.release_400.headline': 'TREK 有史以來最大的一次更新。',
|
||||
'system_notice.release_400.intro':
|
||||
'TREK 有了手機端,也有了相簿書。這一版由十九個人寫成——隨之解決的還有大約一百五十個回報過的 bug。',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK 上手機',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'768px 以下現在是一套獨立的介面——毛玻璃底欄、自己的彈出面板、自己的行程規劃器。用手機開啟 TREK 試試。',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'Journey 的 PDF 變成了一個相簿書設計器。你讓它排版,它就把書排好,然後退到一邊。',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay 補齊了剩下的',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'半天、補休與彈性假、日曆上的學校假期——還有不必從一月開始的休假年度。',
|
||||
'system_notice.release_400.feature_places_title': '地點自己亮相,檔案搬出去',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'在你儲存一個地點之前,圖片和描述會自己填好。上傳的檔案也不必再放在 TREK 所在的磁碟上。',
|
||||
'system_notice.release_400.footnote':
|
||||
'這只是其中四項。4.0.0 還帶來數百項其他改動,從 Collections、Atlas 一直到底層的整個伺服器。',
|
||||
'system_notice.release_400.note_eyebrow': '來自維護者的話',
|
||||
'system_notice.release_400.note_title': '感謝你使用 TREK。',
|
||||
'system_notice.release_400.note_body':
|
||||
'TREK 最初只是我為自己的旅行、用業餘時間做的一個小工具。現在依然如此:晚上、週末,全職工作之外的那些時間。\n\n有一陣子只有我一個人。現在不是了——十九個人一起做出了這一版,還有成千上萬的你們帶著星標、issue、翻譯和 pull request 來到這裡。這一切我都心懷感激。',
|
||||
'system_notice.release_400.promise_label': '承諾',
|
||||
'system_notice.release_400.promise_text': 'TREK 的開源部分永遠免費。沒有付費方案,沒有訂閱,沒有任何套路。我保證。',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'4.0.0 花掉了好幾個星期的深夜——一個手機端、一個相簿書設計器、一次伺服器遷移,大多寫在午夜到兩點之間。這不是抱怨:我喜歡做這件事。只是想誠實地說明,這麼大的一個版本是怎麼從一個業餘專案裡出來的。',
|
||||
'system_notice.release_400.note_closing': '謝謝你來到這裡。',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'是這些支持讓它繼續跑著——伺服器、網域,還有那些變成這樣一個版本的深夜。如果 TREK 對你有價值,請我喝杯咖啡是最直接的支持方式。',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': '在 Ko-fi 上支持我',
|
||||
// The release modal. One stable set of keys: each big release swaps the copy in place.
|
||||
'system_notice.release_notes.eyebrow': '更新已安裝',
|
||||
'system_notice.release_notes.headline': '三件事,TREK 現在自己就能做到。',
|
||||
'system_notice.release_notes.intro':
|
||||
'自行架設的地點 API,從出發到抵達全程規劃的公路旅行,還有重新回到你手中的位置紀錄。',
|
||||
'system_notice.release_notes.features_label': '本次重頭戲',
|
||||
'system_notice.release_notes.features_aside': '遠不止這些',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'第一個自行架設地點 API 的開源旅遊規劃器。收錄 7360 萬個地點,每月重新建置。不需要金鑰,也沒有配額限制。',
|
||||
'system_notice.release_notes.feature_roadtrip_title': '公路旅行擴充套件',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'公路旅行模式會把整段車程規劃好:路線、里程、行車時數與停靠點。這是一個擴充套件,須由管理員啟用後才能使用。',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Dawarich 整合',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'Google Timeline 的自架替代方案,現在可以直接在 TREK 裡檢視。TREK 只讀取,也僅止於讀取,絕不會寫回任何資料。',
|
||||
'system_notice.release_notes.footnote': '除此之外,TREK 的其他部分還有一長串小改動。',
|
||||
'system_notice.release_notes.notes_label': '版本說明',
|
||||
'system_notice.release_notes.note_eyebrow': '來自維護者的話',
|
||||
'system_notice.release_notes.note_title': '是你們讓我一直堅持做 TREK。',
|
||||
'system_notice.release_notes.note_body':
|
||||
'TREK 最初只是我為自己的旅行做的小工具,下班後一點一點寫出來,只因為我想更好地規劃旅行。後來它就再也沒有停止成長。你用到的幾乎每一項功能,都是在全職工作之外,在深夜、週末和火車上做出來的。也有很多個晚上,我會默默地想,這世界上究竟會不會有人打開它。',
|
||||
'system_notice.release_notes.promise_label': '承諾',
|
||||
'system_notice.release_notes.promise_lead': 'TREK 永遠免費。',
|
||||
'system_notice.release_notes.promise_text':
|
||||
'每一項功能、每一次更新,都屬於每一個人。沒有付費方案,沒有訂閱,沒有任何套路。',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'後來,你們真的來了。短短幾個月,就來了成千上萬的你們:有人按星標、回報 bug,有人把它翻譯成我不會說的語言,還有素未謀面的人送出 pull request。直到今天,我每天早上第一件事仍是打開儲存庫看看,而這一切還是有點不太真實。',
|
||||
'system_notice.release_notes.note_closing': '謝謝你來到這裡,Maurice 敬上。',
|
||||
'system_notice.release_notes.support_lead': 'TREK 現在免費,以後也永遠免費,但伺服器、網域和無數個深夜可不是免費的。',
|
||||
'system_notice.release_notes.support_text':
|
||||
'如果它已經在你的旅行中佔有一席之地,請我喝杯咖啡,幫我把下一個版本繼續做出來吧。',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': '在 Ko-fi 上支持我',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -52,40 +52,37 @@ const system_notice: TranslationStrings = {
|
||||
'system_notice.v3014_whitespace_collision.title': '需要操作:用户账户冲突',
|
||||
'system_notice.v3014_whitespace_collision.body':
|
||||
'3.0.14 版本升级检测到一个或多个由存储账户中首尾空白字符引发的用户名或邮箱冲突。受影响的账户已自动重命名。请检查服务器日志中以 **[migration] WHITESPACE COLLISION** 开头的行,以确认哪些账户需要审查。',
|
||||
// 4.0.0 release modal — the release on the left, the note from the maintainer on the right
|
||||
'system_notice.release_400.eyebrow': '更新已安装',
|
||||
'system_notice.release_400.tag': '发布',
|
||||
'system_notice.release_400.headline': 'TREK 有史以来最大的一次更新。',
|
||||
'system_notice.release_400.intro':
|
||||
'TREK 有了手机端,也有了相册书。这一版由十九个人写成——随之解决的还有大约一百五十个报告过的 bug。',
|
||||
'system_notice.release_400.feature_mobile_title': 'TREK 上手机',
|
||||
'system_notice.release_400.feature_mobile_body':
|
||||
'768px 以下现在是一套独立的界面——毛玻璃底栏、自己的弹出面板、自己的行程规划器。用手机打开 TREK 试试。',
|
||||
'system_notice.release_400.feature_studio_title': 'TREK Studio',
|
||||
'system_notice.release_400.feature_studio_badge': 'Beta',
|
||||
'system_notice.release_400.feature_studio_body':
|
||||
'Journey 的 PDF 变成了一个相册书设计器。你让它排版,它就把书排好,然后退到一边。',
|
||||
'system_notice.release_400.feature_vacay_title': 'Vacay 补齐了剩下的',
|
||||
'system_notice.release_400.feature_vacay_body':
|
||||
'半天、调休和弹性假、日历上的学校假期——还有不必从一月开始的假期年度。',
|
||||
'system_notice.release_400.feature_places_title': '地点自己亮相,文件搬出去',
|
||||
'system_notice.release_400.feature_places_body':
|
||||
'在你保存一个地点之前,图片和描述会自己填好。上传的文件也不必再放在 TREK 所在的磁盘上。',
|
||||
'system_notice.release_400.footnote':
|
||||
'这只是其中四项。4.0.0 还带来数百项其他改动,从 Collections、Atlas 一直到底层的整个服务端。',
|
||||
'system_notice.release_400.note_eyebrow': '来自维护者的话',
|
||||
'system_notice.release_400.note_title': '感谢你使用 TREK。',
|
||||
'system_notice.release_400.note_body':
|
||||
'TREK 最初只是我为自己的旅行、用业余时间做的一个小工具。现在依然如此:晚上、周末,全职工作之外的那些时间。\n\n有一阵子只有我一个人。现在不是了——十九个人一起做出了这一版,还有成千上万的你们带着星标、issue、翻译和 pull request 来到这里。这一切我都心怀感激。',
|
||||
'system_notice.release_400.promise_label': '承诺',
|
||||
'system_notice.release_400.promise_text': 'TREK 的开源部分永远免费。没有付费档位,没有订阅,没有套路。我保证。',
|
||||
'system_notice.release_400.note_body_after':
|
||||
'4.0.0 花掉了好几个星期的深夜——一个手机端、一个相册书设计器、一次服务端迁移,大多写在午夜到两点之间。这不是抱怨:我喜欢做这件事。只是想诚实地说明,这么大的一个版本是怎么从一个业余项目里出来的。',
|
||||
'system_notice.release_400.note_closing': '谢谢你来到这里。',
|
||||
'system_notice.release_400.note_signature': '— Maurice',
|
||||
'system_notice.release_400.support_text':
|
||||
'是这些支持让它继续跑着——服务器、域名,还有那些变成这样一个版本的深夜。如果 TREK 对你有价值,请我喝杯咖啡是最直接的支持方式。',
|
||||
'system_notice.release_400.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_400.cta_kofi': '在 Ko-fi 上支持',
|
||||
// The release modal. One stable set of keys: each big release swaps the copy in place.
|
||||
'system_notice.release_notes.eyebrow': '更新已安装',
|
||||
'system_notice.release_notes.headline': '三件事,TREK 现在自己就能做到。',
|
||||
'system_notice.release_notes.intro': '自建的地点 API,从出发到抵达全程规划的公路旅行,还有重新回到你手中的位置历史。',
|
||||
'system_notice.release_notes.features_label': '本次重头戏',
|
||||
'system_notice.release_notes.features_aside': '远不止这些',
|
||||
'system_notice.release_notes.feature_places_title': 'TREK Places API',
|
||||
'system_notice.release_notes.feature_places_body':
|
||||
'第一个自建地点 API 的开源旅行规划器。收录 7360 万个地点,每月重新构建。无需密钥,不限配额。',
|
||||
'system_notice.release_notes.feature_roadtrip_title': '公路旅行扩展',
|
||||
'system_notice.release_notes.feature_roadtrip_body':
|
||||
'公路旅行模式会把整段车程规划好:路线、里程、驾驶时长和停靠点。这是一个扩展,需要管理员开启后才能使用。',
|
||||
'system_notice.release_notes.feature_dawarich_title': 'Dawarich 集成',
|
||||
'system_notice.release_notes.feature_dawarich_body':
|
||||
'Google Timeline 的自托管替代方案,现在可以直接在 TREK 里查看。TREK 只读取,仅此而已,绝不会回写任何数据。',
|
||||
'system_notice.release_notes.footnote': '除此之外,TREK 的其他部分还有一长串小改动。',
|
||||
'system_notice.release_notes.notes_label': '更新说明',
|
||||
'system_notice.release_notes.note_eyebrow': '来自维护者的话',
|
||||
'system_notice.release_notes.note_title': '是你们让我一直坚持做 TREK。',
|
||||
'system_notice.release_notes.note_body':
|
||||
'TREK 最初只是我为自己的旅行做的小工具,下班后一点点写出来,只因为我想更好地规划旅行。后来它就再没停止过成长。你用到的几乎每一样功能,都是在全职工作之外,在深夜、周末和火车上做出来的。也有很多个晚上,我会默默地想,这世上究竟会不会有人打开它。',
|
||||
'system_notice.release_notes.promise_label': '承诺',
|
||||
'system_notice.release_notes.promise_lead': 'TREK 永远免费。',
|
||||
'system_notice.release_notes.promise_text': '每个功能、每次更新,都属于每一个人。没有付费档位,没有订阅,没有套路。',
|
||||
'system_notice.release_notes.note_body_after':
|
||||
'后来,你们真的来了。短短几个月,就来了成千上万的你们:有人点星标、报 bug,有人把它翻译成我不会说的语言,还有素未谋面的人提交 pull request。直到今天,我每天早上第一件事仍是打开仓库看看,而这一切还是有点不像真的。',
|
||||
'system_notice.release_notes.note_closing': '谢谢你来到这里,Maurice 敬上。',
|
||||
'system_notice.release_notes.support_lead': 'TREK 现在免费,以后也永远免费,但服务器、域名和无数个深夜可不是免费的。',
|
||||
'system_notice.release_notes.support_text':
|
||||
'如果它已经在你的旅行中占有一席之地,请我喝杯咖啡,帮我把下一个版本继续做出来吧。',
|
||||
'system_notice.release_notes.cta_bmc': 'Buy me a coffee',
|
||||
'system_notice.release_notes.cta_kofi': '在 Ko-fi 上支持',
|
||||
};
|
||||
export default system_notice;
|
||||
|
||||
@@ -54,32 +54,33 @@ describe('systemNoticeDtoSchema', () => {
|
||||
|
||||
it('accepts a release notice and keeps its optional pieces optional', () => {
|
||||
const base = {
|
||||
id: 'release-4-0-0',
|
||||
id: 'release-notes',
|
||||
display: 'modal' as const,
|
||||
severity: 'info' as const,
|
||||
titleKey: 't',
|
||||
bodyKey: 'b',
|
||||
dismissible: true,
|
||||
release: {
|
||||
version: '4.0.0',
|
||||
version: '4.3.0',
|
||||
eyebrowKey: 'e',
|
||||
tagKey: 'tag',
|
||||
headlineKey: 'h',
|
||||
introKey: 'i',
|
||||
featuresLabelKey: 'fl',
|
||||
features: [
|
||||
{ iconName: 'Smartphone', titleKey: 'f1t', bodyKey: 'f1b' },
|
||||
{ iconName: 'BookOpen', titleKey: 'f2t', bodyKey: 'f2b', badgeKey: 'beta' },
|
||||
{ iconName: 'Database', titleKey: 'f1t', bodyKey: 'f1b' },
|
||||
{ iconName: 'Route', visual: 'roadtrip', titleKey: 'f2t', bodyKey: 'f2b' },
|
||||
],
|
||||
note: {
|
||||
eyebrowKey: 'ne',
|
||||
titleKey: 'nt',
|
||||
bodyKey: 'nb',
|
||||
promiseLabelKey: 'pl',
|
||||
promiseLeadKey: 'plead',
|
||||
promiseTextKey: 'pt',
|
||||
bodyAfterKey: 'nba',
|
||||
closingKey: 'nc',
|
||||
signatureKey: 'ns',
|
||||
},
|
||||
supportLeadKey: 'slead',
|
||||
supportTextKey: 's',
|
||||
},
|
||||
};
|
||||
@@ -89,7 +90,7 @@ describe('systemNoticeDtoSchema', () => {
|
||||
...base,
|
||||
release: {
|
||||
...base.release,
|
||||
stats: [{ value: '~150', labelKey: 'bugs' }],
|
||||
featuresAsideKey: 'fa',
|
||||
notes: { labelKey: 'notes', href: 'https://example.test' },
|
||||
footnoteKey: 'fn',
|
||||
},
|
||||
@@ -107,12 +108,13 @@ describe('systemNoticeDtoSchema', () => {
|
||||
bodyKey: 'b',
|
||||
dismissible: true,
|
||||
release: {
|
||||
version: '4.0.0',
|
||||
version: '4.3.0',
|
||||
eyebrowKey: 'e',
|
||||
tagKey: 'tag',
|
||||
headlineKey: 'h',
|
||||
introKey: 'i',
|
||||
featuresLabelKey: 'fl',
|
||||
features: [],
|
||||
supportLeadKey: 'slead',
|
||||
supportTextKey: 's',
|
||||
},
|
||||
}).success,
|
||||
|
||||
@@ -42,18 +42,15 @@ const noticeCtaSchema = z.discriminatedUnion('kind', [
|
||||
}),
|
||||
]);
|
||||
|
||||
/** One "what changed" row in the release panel: icon, headline, prose, optional badge. */
|
||||
/**
|
||||
* One headline card in the release panel. `visual` names a small illustration the
|
||||
* client draws for it; a name the client does not know falls back to the icon.
|
||||
*/
|
||||
const noticeReleaseFeatureSchema = z.object({
|
||||
iconName: z.string(),
|
||||
visual: z.string().optional(),
|
||||
titleKey: z.string(),
|
||||
bodyKey: z.string(),
|
||||
badgeKey: z.string().optional(),
|
||||
});
|
||||
|
||||
/** A number worth stating next to the release — the figure itself is not translated. */
|
||||
const noticeReleaseStatSchema = z.object({
|
||||
value: z.string(),
|
||||
labelKey: z.string(),
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -63,28 +60,32 @@ const noticeReleaseStatSchema = z.object({
|
||||
* shows lives here rather than inside the component.
|
||||
*/
|
||||
const noticeReleaseSchema = z.object({
|
||||
/** Shown as the display figure ("4.0.0") — a version string, not a semver gate. */
|
||||
/** Shown as the display figure ("4.3.0"), a version string, not a semver gate. */
|
||||
version: z.string(),
|
||||
eyebrowKey: z.string(),
|
||||
tagKey: z.string(),
|
||||
headlineKey: z.string(),
|
||||
introKey: z.string(),
|
||||
featuresLabelKey: z.string(),
|
||||
featuresAsideKey: z.string().optional(),
|
||||
/** Two to four cards; the grid lays out any of those counts. */
|
||||
features: z.array(noticeReleaseFeatureSchema),
|
||||
stats: z.array(noticeReleaseStatSchema).optional(),
|
||||
notes: z.object({ labelKey: z.string(), href: z.string() }).optional(),
|
||||
footnoteKey: z.string().optional(),
|
||||
note: z.object({
|
||||
eyebrowKey: z.string(),
|
||||
titleKey: z.string(),
|
||||
/** Markdown paragraphs above the promise box. */
|
||||
/** Paragraphs above the promise box, separated by a blank line. */
|
||||
bodyKey: z.string(),
|
||||
promiseLabelKey: z.string(),
|
||||
/** The promise's opening sentence, set in bold before the rest. */
|
||||
promiseLeadKey: z.string(),
|
||||
promiseTextKey: z.string(),
|
||||
/** Markdown paragraphs below the promise box. */
|
||||
/** Paragraphs below the promise box, separated by a blank line. */
|
||||
bodyAfterKey: z.string(),
|
||||
closingKey: z.string(),
|
||||
signatureKey: z.string(),
|
||||
}),
|
||||
/** The support footer's opening sentence, set in bold before the rest. */
|
||||
supportLeadKey: z.string(),
|
||||
supportTextKey: z.string(),
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user