diff --git a/client/src/components/Demo/DemoCredits.tsx b/client/src/components/Demo/DemoCredits.tsx new file mode 100644 index 000000000..00acaf481 --- /dev/null +++ b/client/src/components/Demo/DemoCredits.tsx @@ -0,0 +1,76 @@ +import { useEffect, useRef } from 'react'; +import { useTranslation } from '../../i18n'; +import { fs } from '../shared/DialogShell'; +import { + PHOTO_CREDITS, + PUBLIC_DOMAIN, + commonsPage, + creditTitle, + licenseDeed, + type PhotoCredit, +} from './demoCreditsModel'; + +type Translate = ReturnType['t']; + +const LINK = 'underline decoration-edge underline-offset-2 hover:text-content'; + +/** One photo: its title linking to its page on Commons, who took it, and its license linking to the deed. */ +function CreditRow({ credit, t }: { credit: PhotoCredit; t: Translate }) { + const deed = licenseDeed(credit.license); + const license = credit.license === PUBLIC_DOMAIN ? t('demo.credits.publicDomain') : credit.license; + return ( +
  • + + {creditTitle(credit.file)} + + + {t('demo.credits.by', { author: credit.author })} + {deed ? ( + + {license} + + ) : ( + {license} + )} + +
  • + ); +} + +/** + * The credits for the demo's photos, the welcome dialog's second view. Its own + * chunk, loaded when a visitor opens it: only a demo instance shows the + * welcome, and few visitors open its credits. + */ +export default function DemoCredits() { + const { t } = useTranslation(); + const intro = useRef(null); + + // The dialog's body keeps the welcome's scroll position when the credits + // take its place; they start at their top. + useEffect(() => { + intro.current?.scrollIntoView({ block: 'nearest' }); + }, []); + + return ( + <> +

    + {t('demo.credits.intro')} +

    + + + ); +} diff --git a/client/src/components/Demo/DemoWelcome.test.tsx b/client/src/components/Demo/DemoWelcome.test.tsx index a0be84371..25b192ed6 100644 --- a/client/src/components/Demo/DemoWelcome.test.tsx +++ b/client/src/components/Demo/DemoWelcome.test.tsx @@ -1,4 +1,4 @@ -import { act, fireEvent } from '@testing-library/react'; +import { act, fireEvent, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { render, screen } from '../../../tests/helpers/render'; @@ -66,13 +66,14 @@ describe('DemoWelcome', () => { it('FE-COMP-DEMOWELCOME-005: the countdown runs live in the server zone', async () => { vi.useFakeTimers({ shouldAdvanceTime: false }); + // On a whole second, so every tick of the interval lands on one too. vi.setSystemTime(new Date(Date.UTC(2026, 9, 24, 12, 17, 53))); render(); expect(screen.getByTestId('demo-countdown')).toHaveTextContent('42:07'); + // Advancing the fake timers moves the fake clock with them: the fifth tick reads 12:17:58. await act(async () => { - vi.setSystemTime(new Date(Date.UTC(2026, 9, 24, 12, 17, 58))); - vi.advanceTimersByTime(1000); + vi.advanceTimersByTime(5000); }); expect(screen.getByTestId('demo-countdown')).toHaveTextContent('42:02'); }); @@ -89,4 +90,60 @@ describe('DemoWelcome', () => { fireEvent.keyDown(document, { key: 'Escape' }); expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); }); + + it('FE-COMP-DEMOWELCOME-008: the photo credits open in its place and the back button returns', async () => { + const user = userEvent.setup(); + render(); + await user.click(screen.getByRole('button', { name: 'Photo credits' })); + + const list = await screen.findByRole('list', { name: 'Photo credits' }, { timeout: 5000 }); + expect(within(list).getAllByRole('listitem')).toHaveLength(228); + expect(screen.getByText(/come from Wikimedia Commons/)).toBeInTheDocument(); + expect(screen.getByRole('heading', { name: 'Photo credits' })).toBeInTheDocument(); + expect(screen.queryByText('Everything resets every hour')).not.toBeInTheDocument(); + expect(screen.getByRole('dialog', { name: 'Live demo' })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'Back' })).toHaveFocus(); + + await user.click(screen.getByRole('button', { name: 'Back' })); + expect(screen.getByText('Everything resets every hour')).toBeInTheDocument(); + expect(screen.queryByRole('list', { name: 'Photo credits' })).not.toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'Photo credits' })).toHaveFocus(); + }); + + it('FE-COMP-DEMOWELCOME-009: a photo names its title, author and license, each linking to its source', async () => { + const user = userEvent.setup(); + render(); + await user.click(screen.getByRole('button', { name: 'Photo credits' })); + + const title = await screen.findByRole('link', { name: 'Lagoa Rasa (Sete Cidades) 2' }, { timeout: 5000 }); + expect(title).toHaveAttribute('href', 'https://commons.wikimedia.org/wiki/File:Lagoa_Rasa_(Sete_Cidades)_2.jpg'); + expect(title).toHaveAttribute('target', '_blank'); + expect(title).toHaveAttribute('rel', 'noopener noreferrer'); + const row = within(title.closest('li') as HTMLElement); + expect(row.getByText('by Walmaul')).toBeInTheDocument(); + const license = row.getByRole('link', { name: 'CC BY-SA 4.0' }); + expect(license).toHaveAttribute('href', 'https://creativecommons.org/licenses/by-sa/4.0/'); + expect(license).toHaveAttribute('target', '_blank'); + expect(license).toHaveAttribute('rel', 'noopener noreferrer'); + }); + + it('FE-COMP-DEMOWELCOME-010: a public domain photo names it without a deed, and a cleaned author reads as a name', async () => { + const user = userEvent.setup(); + render(); + await user.click(screen.getByRole('button', { name: 'Photo credits' })); + + const abiskoTitle = await screen.findByRole('link', { name: 'AbiskoNationalpark01' }, { timeout: 5000 }); + const abisko = within(abiskoTitle.closest('li') as HTMLElement); + expect(abisko.getByText('Public domain')).toBeInTheDocument(); + expect(abisko.getAllByRole('link')).toHaveLength(1); + + const zinnen = within( + screen.getByRole('link', { name: 'Drei Zinnen Tre Cime di Lavaredo Dolomites' }).closest('li') as HTMLElement + ); + expect(zinnen.getByText('by Wolfgang Moroder')).toBeInTheDocument(); + expect(zinnen.getByRole('link', { name: 'CC BY-SA 3.0' })).toHaveAttribute( + 'href', + 'https://creativecommons.org/licenses/by-sa/3.0/' + ); + }); }); diff --git a/client/src/components/Demo/DemoWelcome.tsx b/client/src/components/Demo/DemoWelcome.tsx index a78cf3d5d..d8774e8c3 100644 --- a/client/src/components/Demo/DemoWelcome.tsx +++ b/client/src/components/Demo/DemoWelcome.tsx @@ -1,5 +1,5 @@ -import { ArrowRight, Clock, ExternalLink, RotateCcw } from 'lucide-react'; -import { useId } from 'react'; +import { ArrowLeft, ArrowRight, Clock, ExternalLink, Images, RotateCcw } from 'lucide-react'; +import { lazy, Suspense, useId } from 'react'; import { useTranslation } from '../../i18n'; import { DialogButton, @@ -9,16 +9,22 @@ import { DialogShell, DialogTile, FooterSpacer, + fs, NEUTRAL_TINT, PILL, - fs, } from '../shared/DialogShell'; +import ErrorBoundary from '../shared/ErrorBoundary'; import TrekIcon from '../shared/TrekIcon'; import { DEMO_FEATURES, DEMO_FULL_VERSION, DEMO_LIMITS, TREK_REPO_URL, type DemoLine } from './demoWelcomeModel'; import { useDemoWelcome } from './useDemoWelcome'; +// The credits and their photo list load when a visitor opens them, not with the dashboard. +const DemoCredits = lazy(() => import('./DemoCredits')); + type Translate = ReturnType['t']; +const FOOTER_LINK = 'inline-flex items-center gap-1.5 font-medium text-content-muted no-underline hover:text-content'; + /** The tiles: what a visitor can open right now, one card each. */ function FeatureGrid({ t }: { t: Translate }) { return ( @@ -57,67 +63,10 @@ function LineList({ lines, tone, t }: { lines: readonly DemoLine[]; tone: 'muted ); } -/** - * The welcome a demo instance opens with: what TREK is, that the demo resets - * on the hour (with the live countdown), what to try right away, what the - * demo leaves out and what the full version adds. Closed by the button, - * Escape or a click on the backdrop, and shown again on the next visit. - */ -export default function DemoWelcome() { - const { t } = useTranslation(); - const labelId = useId(); - const { open, close, countdown } = useDemoWelcome(); - +/** The welcome itself: the hourly reset, the tiles, and the two lists under them. */ +function WelcomeBody({ t }: { t: Translate }) { return ( - - - - } - tint={NEUTRAL_TINT} - labelId={labelId} - onClose={close} - eyebrow={t('demo.welcome.eyebrow')} - title={t('demo.welcome.title')} - sub={t('demo.welcome.tagline')} - subWraps - pills={ - - - {t('demo.welcome.resetIn')} - - {countdown} - - - } - /> - } - footer={ - - - - {t('demo.welcome.repo')} - - - }> - {t('demo.welcome.start')} - - - } - > + <>
    @@ -142,6 +91,115 @@ export default function DemoWelcome() {
    + + ); +} + +/** + * The footer's links: the source code, and the credits for the demo's photos. + * One above the other on a phone, where the footer has no room for both + * beside the button. + */ +function FooterLinks({ t, onCredits, focusCredits }: { t: Translate; onCredits: () => void; focusCredits: boolean }) { + return ( +
    + + + {t('demo.welcome.repo')} + + +
    + ); +} + +/** + * The welcome a demo instance opens with: what TREK is, that the demo resets + * on the hour (with the live countdown), what to try right away, what the + * demo leaves out and what the full version adds. The photo credits open in + * its place and back. Closed by the button, Escape or a click on the + * backdrop, and shown again on the next visit. + */ +export default function DemoWelcome() { + const { t } = useTranslation(); + const labelId = useId(); + const { open, close, countdown, creditsOpen, backFromCredits, openCredits, closeCredits } = useDemoWelcome(); + + return ( + + + + } + tint={NEUTRAL_TINT} + labelId={labelId} + onClose={close} + eyebrow={t('demo.welcome.eyebrow')} + title={t(creditsOpen ? 'demo.credits.title' : 'demo.welcome.title')} + sub={creditsOpen ? undefined : t('demo.welcome.tagline')} + subWraps + pills={ + + + {t('demo.welcome.resetIn')} + + {countdown} + + + } + /> + } + footer={ + + {/* The start button keeps its place in both views, so switching does not move the focus onto it again. */} + {creditsOpen ? ( + } + > + {t('demo.credits.back')} + + ) : ( + + )} + + }> + {t('demo.welcome.start')} + + + } + > + {creditsOpen ? ( + + + + + + ) : ( + + )} ); } diff --git a/client/src/components/Demo/demoCreditsModel.test.ts b/client/src/components/Demo/demoCreditsModel.test.ts new file mode 100644 index 000000000..96904899b --- /dev/null +++ b/client/src/components/Demo/demoCreditsModel.test.ts @@ -0,0 +1,54 @@ +import { describe, expect, it } from 'vitest'; +import { PHOTO_CREDITS, PUBLIC_DOMAIN, commonsPage, creditTitle, licenseDeed } from './demoCreditsModel'; + +describe('demo photo credits', () => { + it('FE-DEMO-CREDITS-001: credits every photo of the demo content, each file once', () => { + expect(PHOTO_CREDITS).toHaveLength(228); + expect(new Set(PHOTO_CREDITS.map((c) => c.file)).size).toBe(228); + for (const { file } of PHOTO_CREDITS) expect(file, file).toMatch(/\.jpe?g$/i); + }); + + it('FE-DEMO-CREDITS-002: every author is a plain name, with no Commons notice or link label left', () => { + for (const { file, author } of PHOTO_CREDITS) { + expect(author.trim(), file).not.toBe(''); + expect(author, file).toBe(author.trim()); + expect(author.length, `${file}: ${author}`).toBeLessThanOrEqual(60); + expect(author, file).not.toMatch(/\s{2,}|\n/); + expect(author, file).not.toMatch( + /Photo was taken|machine-readable|assumed|Feel free|copyright|https?:|User:|\((?:Website|Flickr)\)/i + ); + } + const authorOf = (file: string) => PHOTO_CREDITS.find((c) => c.file === file)?.author; + expect(authorOf('Drei Zinnen Tre Cime di Lavaredo Dolomites.jpg')).toBe('Wolfgang Moroder'); + expect(authorOf('Iceland Godafoss 1972.jpg')).toBe('Roger McLassus'); + expect(authorOf('Arashiyama Bamboo Grove (Unsplash).jpg')).toBe('Erol Ahmed'); + }); + + it('FE-DEMO-CREDITS-003: every license has its deed, except the public domain', () => { + for (const { file, license } of PHOTO_CREDITS) { + if (license === PUBLIC_DOMAIN) expect(licenseDeed(license), file).toBeUndefined(); + else expect(licenseDeed(license), `${file}: ${license}`).toMatch(/^https:\/\/creativecommons\.org\/.+\/$/); + } + }); + + it('FE-DEMO-CREDITS-004: derives the deed from the license name', () => { + expect(licenseDeed('CC BY-SA 4.0')).toBe('https://creativecommons.org/licenses/by-sa/4.0/'); + expect(licenseDeed('CC BY 2.5')).toBe('https://creativecommons.org/licenses/by/2.5/'); + expect(licenseDeed('CC BY-SA 2.0 de')).toBe('https://creativecommons.org/licenses/by-sa/2.0/de/'); + expect(licenseDeed('CC0')).toBe('https://creativecommons.org/publicdomain/zero/1.0/'); + expect(licenseDeed(PUBLIC_DOMAIN)).toBeUndefined(); + expect(licenseDeed('GFDL')).toBeUndefined(); + }); + + it('FE-DEMO-CREDITS-005: shows the title without its extension and links the page on Commons', () => { + expect(creditTitle('Café A Brasileira. Sculpture.jpg')).toBe('Café A Brasileira. Sculpture'); + expect(creditTitle('Svínafellsjökull.JPG')).toBe('Svínafellsjökull'); + expect(creditTitle('No extension')).toBe('No extension'); + expect(commonsPage('Lagoa Rasa (Sete Cidades) 2.jpg')).toBe( + 'https://commons.wikimedia.org/wiki/File:Lagoa_Rasa_(Sete_Cidades)_2.jpg' + ); + expect(commonsPage('Glacier du Géant & Mont Blanc.jpg')).toBe( + 'https://commons.wikimedia.org/wiki/File:Glacier_du_G%C3%A9ant_%26_Mont_Blanc.jpg' + ); + }); +}); diff --git a/client/src/components/Demo/demoCreditsModel.ts b/client/src/components/Demo/demoCreditsModel.ts new file mode 100644 index 000000000..2bebcd56d --- /dev/null +++ b/client/src/components/Demo/demoCreditsModel.ts @@ -0,0 +1,50 @@ +import credits from './photoCredits.json'; + +/** + * One photo of the demo content as Wikimedia Commons credits it: the file's + * name there, its author and the short name of its license. The page on + * Commons, the title to show and the license's deed all follow from these, so + * photoCredits.json holds nothing else. + */ +export interface PhotoCredit { + file: string; + author: string; + license: string; +} + +/** + * Every photo in the demo content, sorted by file name. The authors are the + * plain names: where Commons fills the field with a notice or a link label + * ("This Photo was taken by ...", "(Flickr)"), the list holds the name it + * gives, and where the author asks to be credited in a set form, that form. + */ +export const PHOTO_CREDITS: readonly PhotoCredit[] = credits; + +/** The license name Commons gives a photo nobody holds a copyright in; it has no deed to link. */ +export const PUBLIC_DOMAIN = 'Public domain'; + +const COMMONS_FILE_PAGE = 'https://commons.wikimedia.org/wiki/File:'; + +/** The file's name without its extension, the title Commons shows above the photo. */ +export function creditTitle(file: string): string { + const dot = file.lastIndexOf('.'); + return dot > 0 ? file.slice(0, dot) : file; +} + +/** The file's page on Commons, with its full description and license. */ +export function commonsPage(file: string): string { + return COMMONS_FILE_PAGE + encodeURIComponent(file.replace(/ /g, '_')); +} + +/** + * The deed of a Creative Commons license by the short name Commons gives it: + * "CC BY-SA 4.0", a ported one such as "CC BY-SA 2.0 de", or "CC0". Nothing + * for the public domain, which is no license. + */ +export function licenseDeed(license: string): string | undefined { + if (license === 'CC0') return 'https://creativecommons.org/publicdomain/zero/1.0/'; + const match = /^CC (BY(?:-SA)?) (\d\.\d)(?: ([a-z]{2}))?$/.exec(license); + if (!match) return undefined; + const [, terms, version, port] = match; + return `https://creativecommons.org/licenses/${terms.toLowerCase()}/${version}/${port ? `${port}/` : ''}`; +} diff --git a/client/src/components/Demo/demoWelcomeModel.ts b/client/src/components/Demo/demoWelcomeModel.ts index a7ee71d33..9fc2c6fc0 100644 --- a/client/src/components/Demo/demoWelcomeModel.ts +++ b/client/src/components/Demo/demoWelcomeModel.ts @@ -22,7 +22,7 @@ import { } from 'lucide-react'; /** One thing a visitor can try in the demo right away: a tile of the welcome dialog. */ -export interface DemoFeature { +interface DemoFeature { id: string; icon: LucideIcon; titleKey: string; diff --git a/client/src/components/Demo/photoCredits.json b/client/src/components/Demo/photoCredits.json new file mode 100644 index 000000000..b43454547 --- /dev/null +++ b/client/src/components/Demo/photoCredits.json @@ -0,0 +1,498 @@ +[ + { + "file": "(Venice) - Fondamente zattere - Casa Scarpa.jpg", + "author": "Didier Descouens", + "license": "CC BY-SA 4.0" + }, + { + "file": "+Die Hallgrimskirkja ist das markanteste Bauwerk Reykjaviks. 03.jpg", + "author": "Holger Uwe Schmitt", + "license": "CC BY-SA 4.0" + }, + { + "file": "+Die Hallgrimskirkja ist das markanteste Bauwerk Reykjaviks. 05.jpg", + "author": "Holger Uwe Schmitt", + "license": "CC BY-SA 4.0" + }, + { + "file": "021 Wild smiling harbor seal at Jökulsárlón (Iceland) Photo by Giles Laurent.jpg", + "author": "Giles Laurent", + "license": "CC BY-SA 4.0" + }, + { "file": "03613 ISL Akureyri cruise vessel vapors V P.jpg", "author": "Virtual-Pano", "license": "CC BY-SA 4.0" }, + { "file": "20181110 Fushimi Inari shrine 3.jpg", "author": "Balon Greyjoy", "license": "CC0" }, + { "file": "20181110 Fushimi Inari shrine 4.jpg", "author": "Balon Greyjoy", "license": "CC0" }, + { "file": "20181110 Fushimi Inari shrine 6.jpg", "author": "Balon Greyjoy", "license": "CC0" }, + { "file": "2019-08-01 Zugspitze 7.jpg", "author": "Maksym Kozlenko", "license": "CC BY-SA 4.0" }, + { + "file": "2022-05-28 13-21-39 Heinabergslón and Heinabergsjökull.jpg", + "author": "Hansueli Krapf", + "license": "CC BY-SA 4.0" + }, + { "file": "2022-05-28 13-26-26 Island - Hoffell 118.0.jpg", "author": "Hansueli Krapf", "license": "CC BY-SA 4.0" }, + { + "file": "2022-05-28 13-50-35 Panorama of Heinabergsjökull.jpg", + "author": "Hansueli Krapf", + "license": "CC BY-SA 4.0" + }, + { "file": "2023-11-04 Lycian Way near Kaş.jpg", "author": "Alexkom000", "license": "CC BY 4.0" }, + { "file": "AbiskoNationalpark01.jpg", "author": "Unterrichter at English Wikipedia", "license": "Public domain" }, + { "file": "Almannagjá gorge at Þingvellir National Park.jpg", "author": "Olga Ernst", "license": "CC BY-SA 4.0" }, + { "file": "Almannagjá rift at Þingvellir National Park.jpg", "author": "Olga Ernst", "license": "CC BY-SA 4.0" }, + { "file": "Arashiyama Bamboo Grove (Unsplash).jpg", "author": "Erol Ahmed", "license": "CC0" }, + { "file": "Arashiyama Bamboo Grove.jpg", "author": "Mitchwandrew", "license": "CC BY 4.0" }, + { "file": "Arashiyama-Bamboo-Grove-Sunset.jpg", "author": "Bjørn Christian Tørrissen", "license": "CC BY-SA 4.0" }, + { "file": "ArashiyamaTogetsukyo Kyoto.jpg", "author": "Kentagon", "license": "CC BY-SA 4.0" }, + { "file": "Arnarstapi (port).jpg", "author": "Chmee2/Valtameri", "license": "CC BY 3.0" }, + { "file": "Arnarstapi 2.jpg", "author": "Christian Bickel", "license": "CC BY-SA 2.0 de" }, + { "file": "Arnarstapi 4.jpg", "author": "Christian Bickel", "license": "CC BY-SA 2.0 de" }, + { + "file": "Averau from Fedare at Passo Giau, Belluno, Veneto, Italy, 2025 October.jpg", + "author": "Simo Räsänen", + "license": "CC BY-SA 4.0" + }, + { "file": "Bamboo Forest, Arashiyama, Kyoto, Japan.jpg", "author": "Basile Morin", "license": "CC BY-SA 4.0" }, + { "file": "Bamboo Grove, Arashiyama, Kyoto, Japan.jpg", "author": "Basile Morin", "license": "CC BY-SA 4.0" }, + { "file": "Basalt Arch near Arnarstapi.jpg", "author": "Remarksman", "license": "CC BY 2.0" }, + { + "file": "Basilica di Santa Maria della Salute, Venice (37770336971).jpg", + "author": "Dimitris Kamaras from Athens, Greece", + "license": "CC BY 2.0" + }, + { "file": "Black Sand Beach Iceland, Reynisfjara Beach.jpg", "author": "miketnorton", "license": "CC BY 2.0" }, + { "file": "Bubbly Diamond on the Beach - Iceland.jpg", "author": "Eric Kilby", "license": "CC BY-SA 2.0" }, + { + "file": "Burano Hausfassade Wäsche-20090315-RM-113017.jpg", + "author": "Reinhold Möller", + "license": "CC BY-SA 4.0" + }, + { + "file": "Burano Hausfassade Wäsche-20090315-RM-113043.jpg", + "author": "Reinhold Möller", + "license": "CC BY-SA 4.0" + }, + { "file": "Burano Vendig Aug 2021 4.jpg", "author": "Kasa Fue", "license": "CC BY-SA 4.0" }, + { "file": "Café A Brasileira. Sculpture.jpg", "author": "MFREYNAUD51", "license": "CC BY-SA 4.0" }, + { + "file": "Café de Flore, 172 boulevard Saint-Germain, Paris 6e.jpg", + "author": "Celette", + "license": "CC BY-SA 4.0" + }, + { + "file": "Café Majestic - Porto - Portugal (53283088293).jpg", + "author": "Vitor Oliveira from Torres Vedras, PORTUGAL", + "license": "CC BY-SA 2.0" + }, + { "file": "Café Sperl, Wien.jpg", "author": "Jeremy Thompson", "license": "CC BY 2.0" }, + { "file": "Caffè San Marco-Trieste.jpg", "author": "Tiesse", "license": "Public domain" }, + { "file": "Caffè Sant'Eustachio.JPG", "author": "LPLT", "license": "CC BY-SA 3.0" }, + { "file": "Canale Grande in the morning light - panoramio.jpg", "author": "Schölla Schwarz", "license": "CC BY 3.0" }, + { "file": "Cinque Torri 01.jpg", "author": "Clemens Stockner", "license": "CC BY-SA 4.0" }, + { "file": "Cinque Torri 02.jpg", "author": "Clemens Stockner", "license": "CC BY-SA 4.0" }, + { "file": "Cinque Torri 1.jpg", "author": "kallerna", "license": "CC BY-SA 4.0" }, + { "file": "Cinque Torri, Dolomites - panoramio (1).jpg", "author": "Petr Kraumann", "license": "CC BY 3.0" }, + { "file": "Cinque Torri, Dolomites - panoramio (2).jpg", "author": "Petr Kraumann", "license": "CC BY 3.0" }, + { + "file": "Colourful houses in Corte della Comare, Burano (detail).jpg", + "author": "Marco Ober", + "license": "CC BY-SA 4.0" + }, + { "file": "Croda del Becco and Rifugio Biella 202008.jpg", "author": "Marie-Lan Taÿ Pamart", "license": "CC BY 4.0" }, + { + "file": "Cuernos del Paine in Torres del Paine National Park.jpg", + "author": "Pedro Szekely from Los Angeles, USA", + "license": "CC BY-SA 2.0" + }, + { "file": "Dettifoss 2026 02.jpg", "author": "Syrio", "license": "CC BY-SA 4.0" }, + { "file": "Dettifoss Panorama 01.jpg", "author": "Spike", "license": "CC BY-SA 4.0" }, + { "file": "Dettifoss Panorama 02.jpg", "author": "Spike", "license": "CC BY-SA 4.0" }, + { "file": "Dettifoss Panorama 03.jpg", "author": "Spike", "license": "CC BY-SA 4.0" }, + { "file": "Dorsoduro Rio dei Carmini in Venice.jpg", "author": "Wolfgang Moroder", "license": "CC BY-SA 3.0" }, + { "file": "Dotonbori Osaka Japan01-r.jpg", "author": "Oilstreet", "license": "CC BY 2.5" }, + { "file": "Dotonbori, Osaka, at night, November 2016.jpg", "author": "Martin Falbisoner", "license": "CC BY-SA 4.0" }, + { "file": "Drei Zinnen Tre Cime di Lavaredo Dolomites.jpg", "author": "Wolfgang Moroder", "license": "CC BY-SA 3.0" }, + { "file": "Dyrholaey Arch.jpg", "author": "Eric Kilby", "license": "CC BY-SA 2.0" }, + { + "file": "Dyrhólaey, seen from Reynisfjara, Iceland, 20240720 0831 2824.jpg", + "author": "Jakub Hałun", + "license": "CC BY 4.0" + }, + { "file": "Eibsee und Ammergauer Alpen.jpg", "author": "Octagon", "license": "CC BY 3.0" }, + { + "file": "Ëur de Bredles Secëda Odles y Sas Rigais da Resciesa.jpg", + "author": "Wolfgang Moroder", + "license": "CC BY-SA 4.0" + }, + { "file": "Faloria Cortina d'Ampezzo 10.jpg", "author": "kallerna", "license": "CC BY-SA 4.0" }, + { "file": "Falzarego-N.jpg", "author": "Supakon Mohr", "license": "CC BY-SA 3.0 de" }, + { "file": "Fimmvörðuháls (1).jpg", "author": "Chmee2/Valtameri", "license": "CC BY 3.0" }, + { "file": "Fimmvörðuháls (9).jpg", "author": "Chmee2/Valtameri", "license": "CC BY 3.0" }, + { + "file": "Fimmvorduhals-emergency-hut.jpg", + "author": "Reen Eversdijk from Groningen, The Netherlands", + "license": "CC BY 2.0" + }, + { "file": "Fjaðrárgljúfur 04.jpg", "author": "Syrio", "license": "CC BY-SA 4.0" }, + { "file": "Forcella Nuvolau–Nuvolau lodge trail.jpg", "author": "Marco Ober", "license": "CC BY-SA 4.0" }, + { + "file": "Four ladies wearing a yukata in front of the North Gate of Kiyomizu-dera temple Kyoto Japan.jpg", + "author": "Basile Morin", + "license": "CC BY-SA 4.0" + }, + { + "file": "Frea pass Sella group Pisciadu Dolomites South Tyrol.jpg", + "author": "Wolfgang Moroder", + "license": "CC BY-SA 3.0" + }, + { "file": "Funivia del Lagazuoi (passo Falzarego).jpg", "author": "Ale041VE", "license": "CC BY-SA 4.0" }, + { "file": "Gion Hanamikôji-dôri.jpg", "author": "Yanajin33", "license": "CC BY-SA 4.0" }, + { + "file": "Glacier du Mont Mallet (Glacier du Géant) & Mont Blanc, 2010 July.jpg", + "author": "Ximonic, Simo Räsänen", + "license": "CC BY-SA 3.0" + }, + { "file": "Godafoss 2.jpg", "author": "Tord Dellsen", "license": "CC0" }, + { "file": "Godafoss 3.jpg", "author": "Tord Dellsen", "license": "CC0" }, + { "file": "Godafoss 4.jpg", "author": "Tord Dellsen", "license": "CC0" }, + { "file": "Goðafoss Island.jpg", "author": "Superbass", "license": "CC BY-SA 3.0" }, + { + "file": "Gondola Guido Lorenzi - Son Forca Cristallo Italy - panoramio.jpg", + "author": "Hiroki Ogawa", + "license": "CC BY 3.0" + }, + { "file": "GR20 Corsica Montains-2.jpg", "author": "Hermes from mars", "license": "CC BY-SA 3.0" }, + { + "file": "Grand Canal Santa Maria della Salute Vaporetto Gondola Venice 01.jpg", + "author": "Julian Herzog", + "license": "CC BY 4.0" + }, + { + "file": "Gullfoss, Suðurland, Islandia, 2014-08-16, DD 119.JPG", + "author": "Diego Delso", + "license": "CC BY-SA 4.0" + }, + { "file": "Hallgrímskirkja 1.jpg", "author": "Dmitry Brant", "license": "CC BY-SA 4.0" }, + { "file": "Heinabergsjökull (38322450122).jpg", "author": "Markus Trienke", "license": "CC BY-SA 2.0" }, + { "file": "Hverfjall July 2014.JPG", "author": "Martin Falbisoner", "license": "CC BY-SA 4.0" }, + { "file": "Hverir Námaskarð.jpg", "author": "JavierOlivares", "license": "CC BY-SA 4.0" }, + { "file": "Iceland Dettifoss 1972-4.jpg", "author": "Roger McLassus", "license": "CC BY-SA 3.0" }, + { "file": "Iceland Godafoss 1972.jpg", "author": "Roger McLassus", "license": "CC BY-SA 3.0" }, + { "file": "Il Sentiero degli dei.jpg", "author": "Stiflele", "license": "CC BY-SA 4.0" }, + { + "file": "Illusion, Burano Island. (39893205060).jpg", + "author": "Mihai Lucîț from Baia Mare, Romania", + "license": "CC BY 2.0" + }, + { "file": "Islanda- Þórsmörk.jpg", "author": "Mario Falcetti", "license": "CC BY 4.0" }, + { + "file": "Jökulsárlón glacier lagoon, Iceland, 20240719 0935 2448.jpg", + "author": "Jakub Hałun", + "license": "CC BY 4.0" + }, + { + "file": "Jökulsárlón glacier lagoon, Iceland, 20240719 0936 2452.jpg", + "author": "Jakub Hałun", + "license": "CC BY 4.0" + }, + { + "file": "Jökulsárlón glacier lagoon, Iceland, 20240719 0937 2454.jpg", + "author": "Jakub Hałun", + "license": "CC BY 4.0" + }, + { + "file": "Jökulsárlón glacier lagoon, Iceland, 20240719 0947 2477.jpg", + "author": "Jakub Hałun", + "license": "CC BY 4.0" + }, + { + "file": "Kansai Airport (2660200665).jpg", + "author": "Kentaro Iemoto from Tokyo, Japan", + "license": "CC BY-SA 2.0" + }, + { "file": "Kinkaku-ji in November 2016 -02.jpg", "author": "Martin Falbisoner", "license": "CC BY-SA 4.0" }, + { + "file": "Kinkaku-ji the Golden Temple in Kyoto overlooking the lake - high rez.JPG", + "author": "Jaycangel", + "license": "CC BY-SA 3.0" + }, + { "file": "Kirkjufell in Fog (Unsplash).jpg", "author": "Nicholas Kampouris", "license": "CC0" }, + { "file": "Kirkjufell with its reflection.jpg", "author": "_大面", "license": "CC BY 2.5" }, + { "file": "Kirkjufell, Iceland (Unsplash LoKG7kKx7Zc).jpg", "author": "Steven Diaz", "license": "CC0" }, + { + "file": "Kirkjufell, Vesturland, Islandia, 2014-08-14, DD 091.JPG", + "author": "Diego Delso", + "license": "CC BY-SA 4.0" + }, + { "file": "Kiyomizu-dera, Kyoto, November 2016 -01.jpg", "author": "Martin Falbisoner", "license": "CC BY-SA 4.0" }, + { "file": "Kiyomizu-dera, Kyoto, November 2016 -02.jpg", "author": "Martin Falbisoner", "license": "CC BY-SA 4.0" }, + { "file": "Kiyomizu-dera, Kyoto, November 2016 -03.jpg", "author": "Martin Falbisoner", "license": "CC BY-SA 4.0" }, + { "file": "Kiyomizu-dera, Kyoto, November 2016 -06.jpg", "author": "Martin Falbisoner", "license": "CC BY-SA 4.0" }, + { "file": "Kiyomizu-dera, Kyoto, November 2016 -07.jpg", "author": "Martin Falbisoner", "license": "CC BY-SA 4.0" }, + { "file": "KyotoFushimiInariLarge.jpg", "author": "Paul Vlaar", "license": "CC BY-SA 3.0" }, + { "file": "Lagazuoi 05.jpg", "author": "Clemens Stockner", "license": "CC BY-SA 4.0" }, + { "file": "Lago alla base di Svínafellsjökull 01.jpg", "author": "Syrio", "license": "CC BY-SA 4.0" }, + { "file": "Lago alla base di Svínafellsjökull 02.jpg", "author": "Syrio", "license": "CC BY-SA 4.0" }, + { "file": "Lago di Braies South Tyrol 3.jpg", "author": "kallerna", "license": "CC BY-SA 4.0" }, + { "file": "Lago di Braies South Tyrol 5.jpg", "author": "kallerna", "license": "CC BY-SA 4.0" }, + { "file": "Lago di Braies South Tyrol 6.jpg", "author": "kallerna", "license": "CC BY-SA 4.0" }, + { "file": "Lago di Braies South Tyrol 7.jpg", "author": "kallerna", "license": "CC BY-SA 4.0" }, + { "file": "Lago di Braies South Tyrol 9.jpg", "author": "kallerna", "license": "CC BY-SA 4.0" }, + { + "file": "Lago di Limo, Parco Naturale Fanes - Sennes - Braies (BZ).jpg", + "author": "53cri021", + "license": "CC BY-SA 4.0" + }, + { "file": "Lagoa Rasa (Sete Cidades) 2.jpg", "author": "Walmaul", "license": "CC BY-SA 4.0" }, + { "file": "Lake Ashi & Mt Fuji & Hakone Shrine.jpg", "author": "Charlie fong", "license": "CC BY-SA 4.0" }, + { "file": "Landmannalaugar in summer 2009 (13).jpg", "author": "Chmee2/Valtameri", "license": "CC BY 3.0" }, + { + "file": "Manarola NW Cemetery Corniglia Monterosso Cinque Terre Sep23 A7C 06872.jpg", + "author": "Timothy A. Gonsalves", + "license": "CC BY-SA 4.0" + }, + { "file": "Meiji Jingu Shrine Tokyo Japan.jpg", "author": "MediaByPanda", "license": "CC BY-SA 4.0" }, + { "file": "Meiji shrine in August 2007 5.jpg", "author": "Syced", "license": "CC0" }, + { "file": "Meiji Shrine, Tokyo; April 2009 (02).jpg", "author": "MIKI Yoshihito", "license": "CC BY 2.0" }, + { + "file": "Meiji-jingū main hall vue centrale.jpg", + "author": "Hyppolyte de Saint-Rambert", + "license": "CC BY-SA 4.0" + }, + { "file": "Meiji-jingu-pathway.jpg", "author": "Nightcrafter", "license": "CC BY-SA 4.0" }, + { "file": "Monte Kirkjufell (Luglio 2024).jpg", "author": "Paolova97", "license": "CC BY-SA 4.0" }, + { "file": "Morning light in Venice (33726527456).jpg", "author": "Hervé Simon", "license": "CC BY-SA 2.0" }, + { "file": "Mount Fuji and Shinkansen N700.jpg", "author": "Alpsdake", "license": "CC BY-SA 4.0" }, + { + "file": "Mount Myojingatake and Owakudani Station from Owakudani Valley.JPG", + "author": "そらみみ", + "license": "CC BY-SA 3.0" + }, + { "file": "Mount-Fuji from Tokaido Shinkansen window view.jpg", "author": "Indiana jo", "license": "CC BY-SA 4.0" }, + { + "file": "Mountain and grotto at Reynisfjara Beach in July, 2019.jpg", + "author": "Alexander Grebenkov", + "license": "CC BY 3.0" + }, + { "file": "Múlafossur2.jpg", "author": "Ekrem Canli", "license": "CC BY-SA 4.0" }, + { "file": "Neon Signs in Dotonbori, Osaka 20190415 1.jpg", "author": "DXR", "license": "CC BY-SA 4.0" }, + { + "file": "Neunerspitze, 2968 m und Zehnerspitze 3016 m.jpg", + "author": "2015 Michael 2015", + "license": "CC BY-SA 4.0" + }, + { "file": "NeunerZehnerFanes.JPG", "author": "Alex1011", "license": "CC BY 2.5" }, + { "file": "Nishiki ichiba kyoto.jpg", "author": "Pitan", "license": "CC BY-SA 3.0" }, + { "file": "Old Tokaido - Hakone.jpg", "author": "Quercus acuta", "license": "CC BY-SA 4.0" }, + { "file": "Old Tokaido -01.jpg", "author": "Aimaimyi", "license": "CC BY-SA 3.0" }, + { "file": "On the hillside above Ginkaku-ji (2099332601).jpg", "author": "KimonBerlin", "license": "CC BY-SA 2.0" }, + { "file": "Osaka Dotonbori Canal.jpg", "author": "32linesky", "license": "CC BY-SA 4.0" }, + { + "file": "Owakudani Valley and Mount Kammurigatake near Owakudani Station 1.JPG", + "author": "そらみみ", + "license": "CC BY-SA 3.0" + }, + { + "file": "Owakudani Valley and Mount Kammurigatake near Owakudani Station 2.JPG", + "author": "そらみみ", + "license": "CC BY-SA 3.0" + }, + { "file": "Owakudani Valley near Owakudani Station 2.JPG", "author": "そらみみ", "license": "CC BY-SA 3.0" }, + { "file": "Owakudani Valley near Owakudani Station.JPG", "author": "そらみみ", "license": "CC BY-SA 3.0" }, + { "file": "Palazzo Balbi (Venice).jpg", "author": "Didier Descouens", "license": "CC BY-SA 3.0" }, + { + "file": "Palazzo dei Camerlenghi e Ponte Rialto a Venezia.jpg", + "author": "Wolfgang Moroder", + "license": "CC BY-SA 3.0" + }, + { + "file": "Panorama of Canal Grande and Ponte di Rialto, Venice - September 2017.jpg", + "author": "Martin Falbisoner", + "license": "CC BY-SA 4.0" + }, + { "file": "Passo di Giau.jpg", "author": "Frisia Orientalis", "license": "CC BY-SA 3.0" }, + { "file": "Passo Giau SP638.jpg", "author": "kallerna", "license": "CC BY-SA 4.0" }, + { "file": "Photos at teamlab planets tokyo.jpg", "author": "Sasa0403", "license": "CC BY-SA 4.0" }, + { "file": "Ponte di Rialto facciata ovest di sera.jpg", "author": "Wolfgang Moroder", "license": "CC BY-SA 3.0" }, + { "file": "Ponte di Rialto Venice 1.jpg", "author": "kallerna", "license": "CC BY-SA 4.0" }, + { "file": "Pontile Zattere (Venezia).jpg", "author": "Didier Descouens", "license": "CC BY-SA 4.0" }, + { "file": "Preikestolen Norge.jpg", "author": "Stefan Krause, Germany", "license": "CC BY-SA 3.0" }, + { "file": "Ra Gusela, view from Passo Giau.jpg", "author": "Marco Ober", "license": "CC BY-SA 4.0" }, + { "file": "Reine i Lofoten LC0148.jpg", "author": "Jörg Hempel", "license": "CC BY-SA 2.0 de" }, + { + "file": "Reynisfjara Black Sand Beach Iceland Travel Photography (210387065).jpeg", + "author": "Giuseppe Milo", + "license": "CC BY 3.0" + }, + { + "file": "Reynisfjara, Suðurland, Islandia, 2014-08-17, DD 164.JPG", + "author": "Diego Delso", + "license": "CC BY-SA 4.0" + }, + { + "file": "Reyniskirkja Church,Vík í Mýrdal, Suðurland,Ísland.jpg", + "author": "JavierOlivares", + "license": "CC BY-SA 4.0" + }, + { "file": "Rifugio Fanes 01.JPG", "author": "Bbruno", "license": "CC BY-SA 3.0" }, + { "file": "Rifugio Fanes.jpg", "author": "Llorenzi", "license": "CC BY-SA 3.0" }, + { "file": "Rigi Kulm cross 20210905.jpg", "author": "Daniel Kraft", "license": "CC BY-SA 3.0" }, + { + "file": "Roca de la Ley, Parque Nacional de Þingvellir, Suðurland, Islandia, 2014-08-16, DD 022.JPG", + "author": "Diego Delso", + "license": "CC BY-SA 4.0" + }, + { "file": "Salzwelten vantage point.jpg", "author": "Grandmaster Huon", "license": "CC0" }, + { "file": "San Marco cathedral in Venice.JPG", "author": "Petar Milosevic", "license": "CC BY-SA 4.0" }, + { + "file": "Santa Maria della Salute from Hotel Monaco nightview.jpg", + "author": "Wolfgang Moroder", + "license": "CC BY-SA 3.0" + }, + { "file": "Santa Maria della Salute from Hotel Monaco.jpg", "author": "Wolfgang Moroder", "license": "CC BY-SA 3.0" }, + { "file": "Seljalandsfoss - panoramio (7).jpg", "author": "Zoran Kurelić Rabko", "license": "CC BY-SA 3.0" }, + { "file": "Seljalandsfoss and Gljúfrabúi, July 2019.jpg", "author": "Alexander Grebenkov", "license": "CC BY 3.0" }, + { "file": "Seljalandsfoss July 2014 -1.JPG", "author": "Martin Falbisoner", "license": "CC BY-SA 4.0" }, + { "file": "Seljalandsfoss view from side, July 2019.jpg", "author": "Alexander Grebenkov", "license": "CC BY 3.0" }, + { + "file": "Seljalandsfoss, Suðurland, Islandia, 2014-08-16, DD 189-191 HDR.JPG", + "author": "Diego Delso", + "license": "CC BY-SA 4.0" + }, + { + "file": "Senso-ji Temple @ Asakusa (13824517393).jpg", + "author": "Guilhem Vellut from Annecy, France", + "license": "CC BY 2.0" + }, + { + "file": "Senso-ji Temple @ Asakusa (13824525803).jpg", + "author": "Guilhem Vellut from Annecy, France", + "license": "CC BY 2.0" + }, + { + "file": "Senso-ji Temple @ Asakusa (13824839284).jpg", + "author": "Guilhem Vellut from Annecy, France", + "license": "CC BY 2.0" + }, + { + "file": "Senso-ji Temple @ Asakusa (14019477806).jpg", + "author": "Guilhem Vellut from Annecy, France", + "license": "CC BY 2.0" + }, + { "file": "Seyðisfjörður church 1.jpg", "author": "Saifunny", "license": "CC BY-SA 4.0" }, + { "file": "Seyðisfjörður Sept 2019 1.jpg", "author": "Kasa Fue", "license": "CC BY-SA 4.0" }, + { + "file": "Seydisfjordur, East Iceland (51440969579).jpg", + "author": "Fabio Achilli from Milano, Italy", + "license": "CC BY 2.0" + }, + { + "file": "Seydisfjordur, East Iceland (51441184230).jpg", + "author": "Fabio Achilli from Milano, Italy", + "license": "CC BY 2.0" + }, + { "file": "Seyðisfjörður, Iceland (28328269217).jpg", "author": "Joe deSousa", "license": "CC0" }, + { + "file": "Shadows and windows at Hallgrimskirkja Reykjavik Iceland 2026-02-07 21-21-01 1.jpg", + "author": "G. Edward Johnson", + "license": "CC BY 4.0" + }, + { + "file": "Shariden, Kinkaku-ji, Kyoto, East View 20130811 1.jpg", + "author": "DXR / Daniel Vorndran", + "license": "CC BY-SA 3.0" + }, + { "file": "Shinjuku-West Omoide-Yokocho.jpg", "author": "MaedaAkihiko", "license": "CC BY-SA 4.0" }, + { + "file": "Shinkansen N700S series photographed at Higashi-Tagonoura with Mount Fuji in the background, 10 April 2023.jpg", + "author": "Takeshi Aida", + "license": "CC BY-SA 2.0" + }, + { "file": "Skogafoss-02-2018-gje.jpg", "author": "Gerd Eichmann", "license": "CC BY-SA 4.0" }, + { "file": "Sky Lagoon Cold Plunge.jpg", "author": "Laurenmcl", "license": "CC BY-SA 4.0" }, + { "file": "Soca River Valley, Slovenia.jpg", "author": "Barry", "license": "CC BY 2.0" }, + { + "file": "Start of the Old Hakone Highway (9412055176).jpg", + "author": "Maarten Heerlien from Voorschoten, The Netherlands", + "license": "CC BY 2.0" + }, + { + "file": "Strokkur, Área geotérmica de Geysir, Suðurland, Islandia, 2014-08-16, DD 086.JPG", + "author": "Diego Delso", + "license": "CC BY-SA 4.0" + }, + { "file": "Svínafellsjökull 01.jpg", "author": "Syrio", "license": "CC BY-SA 4.0" }, + { "file": "Svínafellsjökull glacier at sunset.jpg", "author": "Mikołaj Bańka", "license": "CC BY 4.0" }, + { "file": "Svínafellsjökull.JPG", "author": "Bromr at Dutch Wikipedia", "license": "CC BY-SA 3.0" }, + { + "file": "Taroko-Gorge Hualien Taiwan Pudu-Bridge-at-Taroko-National-Park-01.jpg", + "author": "CEphoto, Uwe Aranas", + "license": "CC BY-SA 3.0" + }, + { + "file": "The Lava Fields Of Þórsmörk Iceland (175491845).jpeg", + "author": "Ilya Grigorik", + "license": "CC BY-SA 3.0" + }, + { "file": "The park bench (2669222928).jpg", "author": "Rosino", "license": "CC BY-SA 2.0" }, + { + "file": "The West Highland Way approaching the Heads of Glen Etive and Glen Coe - geograph.org.uk - 5014659.jpg", + "author": "Tim Heaton", + "license": "CC BY-SA 2.0" + }, + { "file": "Tokyo Shibuya Scramble Crossing 2018-10-09.jpg", "author": "Benh LIEU SONG", "license": "CC BY-SA 2.0" }, + { + "file": "Torii on Lake Ashi @ Hakone Shrine (13776878594).jpg", + "author": "Guilhem Vellut from Annecy, France", + "license": "CC BY 2.0" + }, + { + "file": "Torii on Lake Ashi @ Hakone Shrine (13776879364).jpg", + "author": "Guilhem Vellut from Annecy, France", + "license": "CC BY 2.0" + }, + { + "file": "Torii path with lantern at Fushimi Inari Taisha Shrine, Kyoto, Japan.jpg", + "author": "Basile Morin", + "license": "CC BY-SA 4.0" + }, + { "file": "Trolltunga 2.jpg", "author": "Steinar Talmoen", "license": "CC BY-SA 3.0" }, + { "file": "Tsukiji Outer Market -04.jpg", "author": "Aimaimyi", "license": "CC BY-SA 3.0" }, + { "file": "Tsukiji Outer Market -05.jpg", "author": "Aimaimyi", "license": "CC BY-SA 3.0" }, + { "file": "Tsukiji Outer Market -06.jpg", "author": "Aimaimyi", "license": "CC BY-SA 3.0" }, + { "file": "Tsukiji Outer Market 2.jpg", "author": "Aw1805", "license": "CC BY-SA 3.0" }, + { "file": "Ushguli Svaneti Georgia.JPG", "author": "Florian Pinel", "license": "CC BY-SA 3.0" }, + { "file": "Vaporetto grand canal venice.jpg", "author": "John Salatas", "license": "CC BY-SA 4.0" }, + { "file": "Vaporetto, Grand Canal, Venice.jpg", "author": "Peter K Burian", "license": "CC BY-SA 4.0" }, + { "file": "Venice, Canal Grande, Dorsoduro, Plzo Balbi.jpg", "author": "Armin Kleiner", "license": "CC BY-SA 4.0" }, + { "file": "Venice, Italy. Morning light.jpg", "author": "Dupont66", "license": "CC BY 4.0" }, + { "file": "Via ferrata Ivano Dibona - panoramio (1).jpg", "author": "Pavel Špindler", "license": "CC BY 3.0" }, + { "file": "Via ferrata Ivano Dibona - panoramio (2).jpg", "author": "Pavel Špindler", "license": "CC BY 3.0" }, + { "file": "Via Ferrato Ivano Dibona 3.jpg", "author": "Schi11", "license": "CC BY-SA 4.0" }, + { "file": "View from Miradouro do Pico do Arieiro - Madeira 05.jpg", "author": "H. Zell", "license": "CC BY-SA 3.0" }, + { "file": "Vire via ferrata Ivano Dibona.jpg", "author": "Evelyne Chassagneux-Bonini", "license": "CC BY-SA 4.0" }, + { + "file": "Water reflection of Kinkaku-ji Temple a sunny day, Kyoto, Japan.jpg", + "author": "Basile Morin", + "license": "CC BY-SA 4.0" + }, + { + "file": "Water reflection of Kinkaku-ji Temple with blue sky and white clouds, Kyoto, Japan.jpg", + "author": "Basile Morin", + "license": "CC BY-SA 4.0" + }, + { "file": "Water transport in Venice at Rialto bridge.jpg", "author": "Wolfgang Moroder", "license": "CC BY-SA 3.0" }, + { "file": "Waterfalls of Iceland 23 02.jpg", "author": "Hornstrandir1", "license": "CC BY-SA 4.0" }, + { "file": "Wengental 2019-10-18.jpg", "author": "2015 Michael 2015", "license": "CC BY-SA 4.0" }, + { "file": "Wien, Café Central -- 2018 -- 3135.jpg", "author": "Dietmar Rabich", "license": "CC BY-SA 4.0" }, + { "file": "Yanaka Ginza 2.jpg", "author": "Christophe95", "license": "CC BY-SA 4.0" }, + { + "file": "Yanaka Ginza shopping street (4041690725).jpg", + "author": "Yoshikazu TAKADA from Tokyo, Japan", + "license": "CC BY 2.0" + }, + { "file": "Yanaka ginza street.jpg", "author": "Kentin", "license": "CC BY-SA 3.0" }, + { "file": "Yanaka Ginza, Tokyo, Japan (6790100548).jpg", "author": "yeowatzup", "license": "CC BY 2.0" }, + { "file": "Þingvellir, Almannagjá 01.jpg", "author": "Syrio", "license": "CC BY-SA 4.0" }, + { "file": "Þingvellir, Almannagjá 07.jpg", "author": "Syrio", "license": "CC BY-SA 4.0" }, + { "file": "関西国際空港全体写真20220811.jpg", "author": "Ankou1192", "license": "CC BY-SA 4.0" } +] diff --git a/client/src/components/Demo/useDemoWelcome.ts b/client/src/components/Demo/useDemoWelcome.ts index b2e341d79..56e43f8fb 100644 --- a/client/src/components/Demo/useDemoWelcome.ts +++ b/client/src/components/Demo/useDemoWelcome.ts @@ -3,12 +3,20 @@ import { useAuthStore } from '../../store/authStore'; import { formatCountdown, secondsUntilReset } from './demoWelcomeModel'; /** - * The welcome dialog's state: whether it is still open, and the live countdown - * to the next hourly reset, ticking once a second in the server's time zone. + * Whether the photo credits have the dialog: not yet, now, or no longer + * (the visitor came back from them, and the focus returns to their link). + */ +type CreditsView = 'unseen' | 'open' | 'left'; + +/** + * The welcome dialog's state: whether it is still open, whether it shows the + * photo credits in place of the welcome, and the live countdown to the next + * hourly reset, ticking once a second in the server's time zone. */ export function useDemoWelcome() { const timeZone = useAuthStore((s) => s.serverTimezone); const [open, setOpen] = useState(true); + const [credits, setCredits] = useState('unseen'); const [secondsLeft, setSecondsLeft] = useState(() => secondsUntilReset(new Date(), timeZone)); useEffect(() => { @@ -17,5 +25,13 @@ export function useDemoWelcome() { return () => clearInterval(timer); }, [open, timeZone]); - return { open, close: () => setOpen(false), countdown: formatCountdown(secondsLeft) }; + return { + open, + close: () => setOpen(false), + countdown: formatCountdown(secondsLeft), + creditsOpen: credits === 'open', + backFromCredits: credits === 'left', + openCredits: () => setCredits('open'), + closeCredits: () => setCredits('left'), + }; } diff --git a/shared/src/i18n/ar/demo.ts b/shared/src/i18n/ar/demo.ts index 23fe20636..729c76311 100644 --- a/shared/src/i18n/ar/demo.ts +++ b/shared/src/i18n/ar/demo.ts @@ -44,6 +44,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'لوحة إدارة للمستخدمين والإضافات والصلاحيات', 'demo.welcome.repo': 'الشيفرة المصدرية على GitHub', 'demo.welcome.start': 'ابدأ الاستكشاف', + 'demo.welcome.credits': 'حقوق الصور', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'حقوق الصور', + 'demo.credits.intro': + 'صور هذا العرض التجريبي من ويكيميديا كومنز، ولكل صورة الترخيص المذكور معها. ينطبق هذا الترخيص على الصورة وحدها، لا على TREK ولا على بقية العرض التجريبي.', + 'demo.credits.by': 'تصوير {author}', + 'demo.credits.publicDomain': 'ملكية عامة', + 'demo.credits.back': 'رجوع', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'الوضع التجريبي', 'demo.lock.apiKeys': 'لا يمكن إنشاء مفاتيح API في العرض التجريبي.', diff --git a/shared/src/i18n/az/demo.ts b/shared/src/i18n/az/demo.ts index 0693e5a58..edd304248 100644 --- a/shared/src/i18n/az/demo.ts +++ b/shared/src/i18n/az/demo.ts @@ -46,6 +46,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'İstifadəçilər, əlavələr və icazələr üçün idarəetmə paneli', 'demo.welcome.repo': 'GitHub-da mənbə kodu', 'demo.welcome.start': 'Kəşf etməyə başlayın', + 'demo.welcome.credits': 'Foto müəllifləri', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Foto müəllifləri', + 'demo.credits.intro': + 'Bu demodakı fotolar Wikimedia Commons-dan götürülüb və hər biri yanında göstərilən lisenziya ilə yayımlanır. Bu lisenziya yalnız fotoya aiddir, TREK-ə və ya demonun qalan hissəsinə aid deyil.', + 'demo.credits.by': 'Müəllif: {author}', + 'demo.credits.publicDomain': 'İctimai mülkiyyət', + 'demo.credits.back': 'Geri', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Demo rejimi', 'demo.lock.apiKeys': 'Demoda API açarları yaratmaq olmur.', diff --git a/shared/src/i18n/br/demo.ts b/shared/src/i18n/br/demo.ts index 243d843f2..e43aa4490 100644 --- a/shared/src/i18n/br/demo.ts +++ b/shared/src/i18n/br/demo.ts @@ -45,6 +45,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Um painel de administração para usuários, complementos e permissões', 'demo.welcome.repo': 'Código fonte no GitHub', 'demo.welcome.start': 'Começar a explorar', + 'demo.welcome.credits': 'Créditos das fotos', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Créditos das fotos', + 'demo.credits.intro': + 'As fotos desta demo vêm do Wikimedia Commons, cada uma sob a licença indicada junto a ela. Essa licença vale apenas para a foto, não para o TREK nem para o resto da demo.', + 'demo.credits.by': 'por {author}', + 'demo.credits.publicDomain': 'Domínio público', + 'demo.credits.back': 'Voltar', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Modo demonstração', 'demo.lock.apiKeys': 'Não é possível criar chaves de API na demo.', diff --git a/shared/src/i18n/ca/demo.ts b/shared/src/i18n/ca/demo.ts index d2571caef..3a20026ac 100644 --- a/shared/src/i18n/ca/demo.ts +++ b/shared/src/i18n/ca/demo.ts @@ -45,6 +45,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Un tauler d’administració per a usuaris, complements i permisos', 'demo.welcome.repo': 'Codi font a GitHub', 'demo.welcome.start': 'Comença a explorar', + 'demo.welcome.credits': 'Crèdits de les fotos', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Crèdits de les fotos', + 'demo.credits.intro': + 'Les fotos d’aquesta demo provenen de Wikimedia Commons, cadascuna amb la llicència que s’hi indica. Aquesta llicència només s’aplica a la foto, no a TREK ni a la resta de la demo.', + 'demo.credits.by': 'per {author}', + 'demo.credits.publicDomain': 'Domini públic', + 'demo.credits.back': 'Enrere', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Mode demo', 'demo.lock.apiKeys': 'A la demo no es poden crear claus d’API.', diff --git a/shared/src/i18n/cs/demo.ts b/shared/src/i18n/cs/demo.ts index 0ec475cb6..c8e8bd229 100644 --- a/shared/src/i18n/cs/demo.ts +++ b/shared/src/i18n/cs/demo.ts @@ -45,6 +45,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Administraci uživatelů, doplňků a oprávnění', 'demo.welcome.repo': 'Zdrojový kód na GitHubu', 'demo.welcome.start': 'Začít objevovat', + 'demo.welcome.credits': 'Autoři fotografií', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Autoři fotografií', + 'demo.credits.intro': + 'Fotografie v tomto demu pocházejí z Wikimedia Commons, každá pod licencí, která je u ní uvedena. Tato licence platí jen pro fotografii, ne pro TREK ani pro zbytek dema.', + 'demo.credits.by': 'Autor: {author}', + 'demo.credits.publicDomain': 'Volné dílo', + 'demo.credits.back': 'Zpět', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Režim dema', 'demo.lock.apiKeys': 'V demu nelze vytvářet klíče API.', diff --git a/shared/src/i18n/de/demo.ts b/shared/src/i18n/de/demo.ts index 6df6d1860..15697171b 100644 --- a/shared/src/i18n/de/demo.ts +++ b/shared/src/i18n/de/demo.ts @@ -45,6 +45,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Einen Adminbereich für Nutzer, Addons und Berechtigungen', 'demo.welcome.repo': 'Quellcode auf GitHub', 'demo.welcome.start': 'Los geht’s', + 'demo.welcome.credits': 'Bildnachweise', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Bildnachweise', + 'demo.credits.intro': + 'Die Fotos dieser Demo stammen aus Wikimedia Commons, jedes unter der Lizenz, die bei ihm steht. Diese Lizenz gilt nur für das Foto, nicht für TREK oder den Rest der Demo.', + 'demo.credits.by': 'Foto: {author}', + 'demo.credits.publicDomain': 'Gemeinfrei', + 'demo.credits.back': 'Zurück', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Demomodus', 'demo.lock.apiKeys': 'In der Demo lassen sich keine API-Schlüssel erstellen.', diff --git a/shared/src/i18n/en/demo.ts b/shared/src/i18n/en/demo.ts index 1b1efa0c5..b171f0827 100644 --- a/shared/src/i18n/en/demo.ts +++ b/shared/src/i18n/en/demo.ts @@ -46,6 +46,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'An admin panel for users, addons and permissions', 'demo.welcome.repo': 'Source code on GitHub', 'demo.welcome.start': 'Start exploring', + 'demo.welcome.credits': 'Photo credits', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Photo credits', + 'demo.credits.intro': + 'The photos in this demo come from Wikimedia Commons, each under the license named with it. That license applies to the photo only, not to TREK or the rest of the demo.', + 'demo.credits.by': 'by {author}', + 'demo.credits.publicDomain': 'Public domain', + 'demo.credits.back': 'Back', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Demo mode', 'demo.lock.apiKeys': 'API keys cannot be created in the demo.', diff --git a/shared/src/i18n/es/demo.ts b/shared/src/i18n/es/demo.ts index 75fe45c5b..61356a60d 100644 --- a/shared/src/i18n/es/demo.ts +++ b/shared/src/i18n/es/demo.ts @@ -46,6 +46,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Un panel de administración para usuarios, complementos y permisos', 'demo.welcome.repo': 'Código fuente en GitHub', 'demo.welcome.start': 'Empezar a explorar', + 'demo.welcome.credits': 'Créditos de las fotos', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Créditos de las fotos', + 'demo.credits.intro': + 'Las fotos de esta demo proceden de Wikimedia Commons, cada una con la licencia indicada junto a ella. Esa licencia se aplica solo a la foto, no a TREK ni al resto de la demo.', + 'demo.credits.by': 'por {author}', + 'demo.credits.publicDomain': 'Dominio público', + 'demo.credits.back': 'Volver', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Modo demo', 'demo.lock.apiKeys': 'En la demo no se pueden crear claves API.', diff --git a/shared/src/i18n/et/demo.ts b/shared/src/i18n/et/demo.ts index f54f4f0f2..850029699 100644 --- a/shared/src/i18n/et/demo.ts +++ b/shared/src/i18n/et/demo.ts @@ -45,6 +45,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Halduspaneel kasutajate, lisamoodulite ja õiguste jaoks', 'demo.welcome.repo': 'Lähtekood GitHubis', 'demo.welcome.start': 'Alusta avastamist', + 'demo.welcome.credits': 'Fotode autorid', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Fotode autorid', + 'demo.credits.intro': + 'Selle demo fotod pärinevad Wikimedia Commonsist, igaüks selle juures märgitud litsentsiga. See litsents kehtib ainult foto kohta, mitte TREKi ega ülejäänud demo kohta.', + 'demo.credits.by': 'Autor: {author}', + 'demo.credits.publicDomain': 'Avalik omand', + 'demo.credits.back': 'Tagasi', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Demorežiim', 'demo.lock.apiKeys': 'Demos ei saa API-võtmeid luua.', diff --git a/shared/src/i18n/fr/demo.ts b/shared/src/i18n/fr/demo.ts index 3173a6c90..0c8ab6901 100644 --- a/shared/src/i18n/fr/demo.ts +++ b/shared/src/i18n/fr/demo.ts @@ -47,6 +47,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Un espace d’administration pour les utilisateurs, modules et permissions', 'demo.welcome.repo': 'Code source sur GitHub', 'demo.welcome.start': 'Commencer la visite', + 'demo.welcome.credits': 'Crédits photo', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Crédits photo', + 'demo.credits.intro': + 'Les photos de cette démo proviennent de Wikimedia Commons, chacune sous la licence indiquée à côté. Cette licence s’applique uniquement à la photo, pas à TREK ni au reste de la démo.', + 'demo.credits.by': 'par {author}', + 'demo.credits.publicDomain': 'Domaine public', + 'demo.credits.back': 'Retour', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Mode démo', 'demo.lock.apiKeys': 'Impossible de créer des clés API dans la démo.', diff --git a/shared/src/i18n/gr/demo.ts b/shared/src/i18n/gr/demo.ts index 2ce75e030..595220605 100644 --- a/shared/src/i18n/gr/demo.ts +++ b/shared/src/i18n/gr/demo.ts @@ -46,6 +46,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Πίνακα διαχείρισης για χρήστες, πρόσθετα και δικαιώματα', 'demo.welcome.repo': 'Πηγαίος κώδικας στο GitHub', 'demo.welcome.start': 'Ξεκίνα την εξερεύνηση', + 'demo.welcome.credits': 'Πηγές φωτογραφιών', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Πηγές φωτογραφιών', + 'demo.credits.intro': + 'Οι φωτογραφίες αυτής της επίδειξης προέρχονται από το Wikimedia Commons, η καθεμία με την άδεια που αναγράφεται δίπλα της. Η άδεια αυτή ισχύει μόνο για τη φωτογραφία, όχι για το TREK ή την υπόλοιπη επίδειξη.', + 'demo.credits.by': 'Φωτογραφία: {author}', + 'demo.credits.publicDomain': 'Κοινό κτήμα', + 'demo.credits.back': 'Πίσω', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Λειτουργία επίδειξης', 'demo.lock.apiKeys': 'Στην επίδειξη δεν δημιουργούνται κλειδιά API.', diff --git a/shared/src/i18n/hu/demo.ts b/shared/src/i18n/hu/demo.ts index 42fa55906..8f0037583 100644 --- a/shared/src/i18n/hu/demo.ts +++ b/shared/src/i18n/hu/demo.ts @@ -46,6 +46,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Adminfelület felhasználókhoz, kiegészítőkhöz és jogosultságokhoz', 'demo.welcome.repo': 'Forráskód a GitHubon', 'demo.welcome.start': 'Felfedezés indítása', + 'demo.welcome.credits': 'Fotók szerzői', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Fotók szerzői', + 'demo.credits.intro': + 'A demó fotói a Wikimedia Commonsról származnak, mindegyik a mellette feltüntetett licenccel. Ez a licenc csak a fotóra vonatkozik, a TREK-re és a demó többi részére nem.', + 'demo.credits.by': 'Fotó: {author}', + 'demo.credits.publicDomain': 'Közkincs', + 'demo.credits.back': 'Vissza', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Demó mód', 'demo.lock.apiKeys': 'A demóban nem hozhatók létre API-kulcsok.', diff --git a/shared/src/i18n/id/demo.ts b/shared/src/i18n/id/demo.ts index b1b9a5a7f..7aa187229 100644 --- a/shared/src/i18n/id/demo.ts +++ b/shared/src/i18n/id/demo.ts @@ -47,6 +47,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Panel admin untuk pengguna, addon, dan izin', 'demo.welcome.repo': 'Kode sumber di GitHub', 'demo.welcome.start': 'Mulai menjelajah', + 'demo.welcome.credits': 'Kredit foto', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Kredit foto', + 'demo.credits.intro': + 'Foto dalam demo ini berasal dari Wikimedia Commons, masing-masing dengan lisensi yang tertera di sampingnya. Lisensi itu hanya berlaku untuk fotonya, bukan untuk TREK atau bagian lain demo ini.', + 'demo.credits.by': 'oleh {author}', + 'demo.credits.publicDomain': 'Domain publik', + 'demo.credits.back': 'Kembali', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Mode demo', 'demo.lock.apiKeys': 'Kunci API tidak dapat dibuat di demo.', diff --git a/shared/src/i18n/it/demo.ts b/shared/src/i18n/it/demo.ts index e4afdfe26..72da3f3db 100644 --- a/shared/src/i18n/it/demo.ts +++ b/shared/src/i18n/it/demo.ts @@ -46,6 +46,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Un pannello di amministrazione per utenti, componenti aggiuntivi e permessi', 'demo.welcome.repo': 'Codice sorgente su GitHub', 'demo.welcome.start': 'Inizia a esplorare', + 'demo.welcome.credits': 'Crediti fotografici', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Crediti fotografici', + 'demo.credits.intro': + 'Le foto di questa demo provengono da Wikimedia Commons, ognuna con la licenza indicata accanto. Quella licenza vale solo per la foto, non per TREK né per il resto della demo.', + 'demo.credits.by': 'Foto di {author}', + 'demo.credits.publicDomain': 'Pubblico dominio', + 'demo.credits.back': 'Indietro', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Modalità demo', 'demo.lock.apiKeys': 'Nella demo non si possono creare chiavi API.', diff --git a/shared/src/i18n/ja/demo.ts b/shared/src/i18n/ja/demo.ts index 84a35c35c..645b16d22 100644 --- a/shared/src/i18n/ja/demo.ts +++ b/shared/src/i18n/ja/demo.ts @@ -43,6 +43,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'ユーザー、アドオン、権限を管理する管理画面', 'demo.welcome.repo': 'GitHub のソースコード', 'demo.welcome.start': '使ってみる', + 'demo.welcome.credits': '写真のクレジット', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': '写真のクレジット', + 'demo.credits.intro': + 'このデモの写真は Wikimedia Commons のもので、それぞれ横に記載したライセンスで公開されています。そのライセンスは写真にのみ適用され、TREK やデモのほかの部分には適用されません。', + 'demo.credits.by': '撮影:{author}', + 'demo.credits.publicDomain': 'パブリックドメイン', + 'demo.credits.back': '戻る', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'デモモード', 'demo.lock.apiKeys': 'デモでは API キーを作成できません。', diff --git a/shared/src/i18n/ko/demo.ts b/shared/src/i18n/ko/demo.ts index bbdd047fe..59da09fbe 100644 --- a/shared/src/i18n/ko/demo.ts +++ b/shared/src/i18n/ko/demo.ts @@ -43,6 +43,14 @@ const demo: TranslationStrings = { 'demo.full.admin': '사용자, 애드온, 권한을 위한 관리자 패널', 'demo.welcome.repo': 'GitHub의 소스 코드', 'demo.welcome.start': '둘러보기 시작', + 'demo.welcome.credits': '사진 출처', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': '사진 출처', + 'demo.credits.intro': + '이 데모의 사진은 Wikimedia Commons에서 가져왔으며, 각 사진에는 함께 표시된 라이선스가 적용됩니다. 이 라이선스는 사진에만 적용되며 TREK이나 데모의 나머지 부분에는 적용되지 않습니다.', + 'demo.credits.by': '촬영: {author}', + 'demo.credits.publicDomain': '퍼블릭 도메인', + 'demo.credits.back': '뒤로', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': '데모 모드', 'demo.lock.apiKeys': '데모에서는 API 키를 만들 수 없습니다.', diff --git a/shared/src/i18n/nl/demo.ts b/shared/src/i18n/nl/demo.ts index 5fc48fd77..7ef7ccd8d 100644 --- a/shared/src/i18n/nl/demo.ts +++ b/shared/src/i18n/nl/demo.ts @@ -45,6 +45,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Een beheerpaneel voor gebruikers, add-ons en rechten', 'demo.welcome.repo': 'Broncode op GitHub', 'demo.welcome.start': 'Begin met verkennen', + 'demo.welcome.credits': 'Fotoverantwoording', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Fotoverantwoording', + 'demo.credits.intro': + 'De foto’s in deze demo komen van Wikimedia Commons, elk onder de licentie die erbij staat. Die licentie geldt alleen voor de foto, niet voor TREK of de rest van de demo.', + 'demo.credits.by': 'door {author}', + 'demo.credits.publicDomain': 'Publiek domein', + 'demo.credits.back': 'Terug', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Demomodus', 'demo.lock.apiKeys': 'In de demo kun je geen API-sleutels aanmaken.', diff --git a/shared/src/i18n/pl/demo.ts b/shared/src/i18n/pl/demo.ts index a2d47194d..65e462e07 100644 --- a/shared/src/i18n/pl/demo.ts +++ b/shared/src/i18n/pl/demo.ts @@ -45,6 +45,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Panel administracyjny dla użytkowników, dodatków i uprawnień', 'demo.welcome.repo': 'Kod źródłowy na GitHubie', 'demo.welcome.start': 'Zacznij odkrywać', + 'demo.welcome.credits': 'Autorzy zdjęć', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Autorzy zdjęć', + 'demo.credits.intro': + 'Zdjęcia w tym demo pochodzą z Wikimedia Commons, każde na licencji podanej przy nim. Ta licencja dotyczy tylko zdjęcia, a nie TREK ani reszty demo.', + 'demo.credits.by': 'fot. {author}', + 'demo.credits.publicDomain': 'Domena publiczna', + 'demo.credits.back': 'Wstecz', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Tryb demo', 'demo.lock.apiKeys': 'W demie nie można tworzyć kluczy API.', diff --git a/shared/src/i18n/ru/demo.ts b/shared/src/i18n/ru/demo.ts index 9b9dfffc4..612517ec7 100644 --- a/shared/src/i18n/ru/demo.ts +++ b/shared/src/i18n/ru/demo.ts @@ -45,6 +45,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Панель администратора для пользователей, дополнений и прав', 'demo.welcome.repo': 'Исходный код на GitHub', 'demo.welcome.start': 'Начать знакомство', + 'demo.welcome.credits': 'Авторы фотографий', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Авторы фотографий', + 'demo.credits.intro': + 'Фотографии в этой демоверсии взяты с Wikimedia Commons, каждая под лицензией, указанной рядом с ней. Эта лицензия распространяется только на фотографию, а не на TREK или остальную демоверсию.', + 'demo.credits.by': 'Фото: {author}', + 'demo.credits.publicDomain': 'Общественное достояние', + 'demo.credits.back': 'Назад', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Деморежим', 'demo.lock.apiKeys': 'В демоверсии нельзя создать ключи API.', diff --git a/shared/src/i18n/sk/demo.ts b/shared/src/i18n/sk/demo.ts index 7111d970d..bae5e2708 100644 --- a/shared/src/i18n/sk/demo.ts +++ b/shared/src/i18n/sk/demo.ts @@ -45,6 +45,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Administráciu používateľov, doplnkov a oprávnení', 'demo.welcome.repo': 'Zdrojový kód na GitHube', 'demo.welcome.start': 'Začať objavovať', + 'demo.welcome.credits': 'Autori fotografií', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Autori fotografií', + 'demo.credits.intro': + 'Fotografie v tomto deme pochádzajú z Wikimedia Commons, každá pod licenciou, ktorá je pri nej uvedená. Táto licencia platí len pre fotografiu, nie pre TREK ani pre zvyšok dema.', + 'demo.credits.by': 'Autor: {author}', + 'demo.credits.publicDomain': 'Voľné dielo', + 'demo.credits.back': 'Späť', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Režim dema', 'demo.lock.apiKeys': 'V deme nie je možné vytvárať kľúče API.', diff --git a/shared/src/i18n/sv/demo.ts b/shared/src/i18n/sv/demo.ts index c59c87e29..fb1fac5ad 100644 --- a/shared/src/i18n/sv/demo.ts +++ b/shared/src/i18n/sv/demo.ts @@ -45,6 +45,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'En adminpanel för användare, tillägg och behörigheter', 'demo.welcome.repo': 'Källkod på GitHub', 'demo.welcome.start': 'Börja utforska', + 'demo.welcome.credits': 'Bildkällor', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Bildkällor', + 'demo.credits.intro': + 'Bilderna i den här demon kommer från Wikimedia Commons, var och en under licensen som anges vid den. Licensen gäller bara bilden, inte TREK eller resten av demon.', + 'demo.credits.by': 'Foto: {author}', + 'demo.credits.publicDomain': 'Allmän egendom', + 'demo.credits.back': 'Tillbaka', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Demoläge', 'demo.lock.apiKeys': 'I demon går det inte att skapa API-nycklar.', diff --git a/shared/src/i18n/th/demo.ts b/shared/src/i18n/th/demo.ts index a82d5973b..a4387ba4c 100644 --- a/shared/src/i18n/th/demo.ts +++ b/shared/src/i18n/th/demo.ts @@ -44,6 +44,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'แผงผู้ดูแลระบบสำหรับผู้ใช้ ส่วนเสริม และสิทธิ์', 'demo.welcome.repo': 'ซอร์สโค้ดบน GitHub', 'demo.welcome.start': 'เริ่มสำรวจ', + 'demo.welcome.credits': 'เครดิตภาพถ่าย', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'เครดิตภาพถ่าย', + 'demo.credits.intro': + 'ภาพถ่ายในเดโมนี้มาจาก Wikimedia Commons โดยแต่ละภาพใช้สัญญาอนุญาตที่ระบุไว้คู่กัน สัญญาอนุญาตนั้นใช้กับภาพถ่ายเท่านั้น ไม่ใช่กับ TREK หรือส่วนอื่นของเดโม', + 'demo.credits.by': 'ภาพโดย {author}', + 'demo.credits.publicDomain': 'สาธารณสมบัติ', + 'demo.credits.back': 'ย้อนกลับ', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'โหมดเดโม', 'demo.lock.apiKeys': 'สร้างคีย์ API ในเดโมไม่ได้', diff --git a/shared/src/i18n/tr/demo.ts b/shared/src/i18n/tr/demo.ts index 416b59037..f3d34a45e 100644 --- a/shared/src/i18n/tr/demo.ts +++ b/shared/src/i18n/tr/demo.ts @@ -46,6 +46,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Kullanıcılar, eklentiler ve izinler için yönetim paneli', 'demo.welcome.repo': 'GitHub’da kaynak kodu', 'demo.welcome.start': 'Keşfetmeye başla', + 'demo.welcome.credits': 'Fotoğraf kaynakları', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Fotoğraf kaynakları', + 'demo.credits.intro': + 'Bu demodaki fotoğraflar Wikimedia Commons’tan geliyor, her biri yanında belirtilen lisansla. Bu lisans yalnızca fotoğraf için geçerli, TREK ya da demonun geri kalanı için değil.', + 'demo.credits.by': 'Fotoğraf: {author}', + 'demo.credits.publicDomain': 'Kamu malı', + 'demo.credits.back': 'Geri', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Demo modu', 'demo.lock.apiKeys': 'Demoda API anahtarı oluşturulamaz.', diff --git a/shared/src/i18n/uk/demo.ts b/shared/src/i18n/uk/demo.ts index 995f923eb..2de0ac917 100644 --- a/shared/src/i18n/uk/demo.ts +++ b/shared/src/i18n/uk/demo.ts @@ -45,6 +45,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Панель адміністратора для користувачів, доповнень і прав', 'demo.welcome.repo': 'Вихідний код на GitHub', 'demo.welcome.start': 'Почати знайомство', + 'demo.welcome.credits': 'Автори фотографій', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Автори фотографій', + 'demo.credits.intro': + 'Фотографії в цій демоверсії взято з Wikimedia Commons, кожну під ліцензією, зазначеною поруч. Ця ліцензія стосується лише фотографії, а не TREK чи решти демоверсії.', + 'demo.credits.by': 'Фото: {author}', + 'demo.credits.publicDomain': 'Суспільне надбання', + 'demo.credits.back': 'Назад', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Деморежим', 'demo.lock.apiKeys': 'У демоверсії не можна створити ключі API.', diff --git a/shared/src/i18n/vi/demo.ts b/shared/src/i18n/vi/demo.ts index 6f479e5ce..fdc87917f 100644 --- a/shared/src/i18n/vi/demo.ts +++ b/shared/src/i18n/vi/demo.ts @@ -48,6 +48,14 @@ const demo: TranslationStrings = { 'demo.full.admin': 'Trang quản trị cho người dùng, tiện ích và quyền', 'demo.welcome.repo': 'Mã nguồn trên GitHub', 'demo.welcome.start': 'Bắt đầu khám phá', + 'demo.welcome.credits': 'Nguồn ảnh', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': 'Nguồn ảnh', + 'demo.credits.intro': + 'Ảnh trong bản demo này lấy từ Wikimedia Commons, mỗi ảnh theo giấy phép ghi kèm. Giấy phép đó chỉ áp dụng cho ảnh, không áp dụng cho TREK hay phần còn lại của bản demo.', + 'demo.credits.by': 'Ảnh: {author}', + 'demo.credits.publicDomain': 'Phạm vi công cộng', + 'demo.credits.back': 'Quay lại', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': 'Chế độ demo', 'demo.lock.apiKeys': 'Không thể tạo khóa API trong bản demo.', diff --git a/shared/src/i18n/zh-TW/demo.ts b/shared/src/i18n/zh-TW/demo.ts index 3b202a941..1c6830cbe 100644 --- a/shared/src/i18n/zh-TW/demo.ts +++ b/shared/src/i18n/zh-TW/demo.ts @@ -41,6 +41,14 @@ const demo: TranslationStrings = { 'demo.full.admin': '管理使用者、附加元件和權限的管理面板', 'demo.welcome.repo': 'GitHub 上的原始碼', 'demo.welcome.start': '開始探索', + 'demo.welcome.credits': '圖片來源', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': '圖片來源', + 'demo.credits.intro': + '本展示中的照片來自 Wikimedia Commons,每張照片都採用其旁邊註明的授權條款。該授權僅適用於照片本身,不適用於 TREK 或展示的其他部分。', + 'demo.credits.by': '攝影:{author}', + 'demo.credits.publicDomain': '公有領域', + 'demo.credits.back': '返回', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': '展示模式', 'demo.lock.apiKeys': '展示中無法建立 API 金鑰。', diff --git a/shared/src/i18n/zh/demo.ts b/shared/src/i18n/zh/demo.ts index 83003ba0b..67cf54513 100644 --- a/shared/src/i18n/zh/demo.ts +++ b/shared/src/i18n/zh/demo.ts @@ -41,6 +41,14 @@ const demo: TranslationStrings = { 'demo.full.admin': '管理用户、附加组件和权限的管理面板', 'demo.welcome.repo': 'GitHub 上的源代码', 'demo.welcome.start': '开始探索', + 'demo.welcome.credits': '图片来源', + // The photo credits, the welcome dialog's second view (components/Demo/DemoCredits). + 'demo.credits.title': '图片来源', + 'demo.credits.intro': + '本演示中的照片来自 Wikimedia Commons,每张照片都采用其旁边注明的许可协议。该许可仅适用于照片本身,不适用于 TREK 或演示的其他部分。', + 'demo.credits.by': '摄影:{author}', + 'demo.credits.publicDomain': '公有领域', + 'demo.credits.back': '返回', // The lock over a section the shared demo account may not change (components/Demo/DemoLock). 'demo.lock.badge': '演示模式', 'demo.lock.apiKeys': '演示中无法创建 API 密钥。',