feat(map): amap as map api provider and display template

This commit is contained in:
A1phaN
2026-09-07 10:04:12 +08:00
committed by Maurice
parent a066c94ec5
commit 57eac32f9f
92 changed files with 2910 additions and 70 deletions
+3
View File
@@ -77,6 +77,8 @@ export const apiKeysUpdateRequestSchema = z.object({
maps_api_key: z.string().nullable().optional(),
openweather_api_key: z.string().nullable().optional(),
unsplash_api_key: z.string().nullable().optional(),
/** Amap (高德) web-service key — the places provider an install in China uses. */
amap_api_key: z.string().nullable().optional(),
});
export type ApiKeysUpdateRequest = z.infer<typeof apiKeysUpdateRequestSchema>;
@@ -84,6 +86,7 @@ export const settingsUpdateRequestSchema = z.object({
maps_api_key: z.string().nullable().optional(),
openweather_api_key: z.string().nullable().optional(),
unsplash_api_key: z.string().nullable().optional(),
amap_api_key: z.string().nullable().optional(),
username: z.string().optional(),
email: z.string().optional(),
});
+103
View File
@@ -0,0 +1,103 @@
import { fromAmapLocation, gcj02ToWgs84, isOutsideChina, toAmapLocation, wgs84ToGcj02 } from './gcj02';
import { describe, expect, it } from 'vitest';
/** Metres between two coordinates — good enough for an assertion at this scale. */
function metresApart(aLat: number, aLng: number, bLat: number, bLng: number): number {
const R = 6371000;
const dLat = ((bLat - aLat) * Math.PI) / 180;
const dLng = ((bLng - aLng) * Math.PI) / 180;
const mLat = ((aLat + bLat) / 2) * (Math.PI / 180);
const x = dLng * Math.cos(mLat);
return Math.sqrt(dLat * dLat + x * x) * R;
}
describe('isOutsideChina', () => {
it('covers the mainland, Hong Kong and Taiwan', () => {
expect(isOutsideChina(39.9042, 116.4074)).toBe(false); // Beijing
expect(isOutsideChina(22.3193, 114.1694)).toBe(false); // Hong Kong
expect(isOutsideChina(25.033, 121.5654)).toBe(false); // Taipei
});
it('excludes the rest of the world so a foreign trip is never shifted', () => {
expect(isOutsideChina(48.8566, 2.3522)).toBe(true); // Paris
expect(isOutsideChina(35.6762, 139.6503)).toBe(true); // Tokyo
expect(isOutsideChina(-33.8688, 151.2093)).toBe(true); // Sydney
});
it('treats a non-finite coordinate as outside rather than shifting NaN', () => {
expect(isOutsideChina(Number.NaN, 116)).toBe(true);
expect(isOutsideChina(39, Number.POSITIVE_INFINITY)).toBe(true);
});
});
describe('wgs84ToGcj02', () => {
// Reference values from the published approximation every coordtransform
// implementation shares; the tolerance is the metre-or-two the algorithm is
// accurate to, not a precision claim about our arithmetic.
it('shifts Tiananmen Square by the expected few hundred metres', () => {
const gcj = wgs84ToGcj02(39.90869, 116.39124);
expect(gcj.lat).toBeCloseTo(39.91009, 4);
expect(gcj.lng).toBeCloseTo(116.39745, 4);
// The whole point of the datum: the offset is big enough to be visibly wrong
// on a map if it were skipped.
expect(metresApart(39.90869, 116.39124, gcj.lat, gcj.lng)).toBeGreaterThan(300);
});
it('leaves a coordinate outside China exactly as it came in', () => {
const paris = wgs84ToGcj02(48.8566, 2.3522);
expect(paris).toEqual({ lat: 48.8566, lng: 2.3522 });
});
});
describe('gcj02ToWgs84', () => {
it('round-trips to sub-metre accuracy across China', () => {
const points: [number, number][] = [
[39.90869, 116.39124], // Beijing
[31.2304, 121.4737], // Shanghai
[22.5431, 114.0579], // Shenzhen
[29.6534, 91.1719], // Lhasa — far west, where the offset is largest
[43.8256, 87.6168], // Ürümqi
[18.2528, 109.5119], // Sanya — far south
];
for (const [lat, lng] of points) {
const gcj = wgs84ToGcj02(lat, lng);
const back = gcj02ToWgs84(gcj.lat, gcj.lng);
expect(metresApart(lat, lng, back.lat, back.lng)).toBeLessThan(1);
}
});
it('is the exact inverse, not the subtract-the-same-offset shortcut', () => {
// The shortcut is out by a few metres; this asserts we are well inside that.
const gcj = wgs84ToGcj02(39.90869, 116.39124);
const back = gcj02ToWgs84(gcj.lat, gcj.lng);
expect(back.lat).toBeCloseTo(39.90869, 7);
expect(back.lng).toBeCloseTo(116.39124, 7);
});
it('leaves a coordinate outside China alone', () => {
expect(gcj02ToWgs84(35.6762, 139.6503)).toEqual({ lat: 35.6762, lng: 139.6503 });
});
});
describe('toAmapLocation', () => {
it('emits lng,lat in GCJ-02 with six decimals', () => {
expect(toAmapLocation(39.90869, 116.39124)).toBe('116.397481,39.910091');
});
});
describe('fromAmapLocation', () => {
it('parses lng,lat back into WGS-84', () => {
const parsed = fromAmapLocation('116.397481,39.910091');
expect(parsed).not.toBeNull();
expect(metresApart(39.90869, 116.39124, parsed!.lat, parsed!.lng)).toBeLessThan(1);
});
it('returns null for the shapes Amap actually sends for a POI with no geometry', () => {
expect(fromAmapLocation([])).toBeNull();
expect(fromAmapLocation('')).toBeNull();
expect(fromAmapLocation(undefined)).toBeNull();
expect(fromAmapLocation('116.397481')).toBeNull();
expect(fromAmapLocation('nope,nope')).toBeNull();
});
});
+153
View File
@@ -0,0 +1,153 @@
/**
* WGS-84 ⇄ GCJ-02 conversion.
*
* Everything TREK stores and draws is WGS-84: the database columns, Nominatim,
* Overpass, OSRM, GPX and KML, and every Leaflet/MapLibre coordinate. Chinese
* providers are not allowed to publish that datum — Amap (高德) returns and
* expects GCJ-02, the "Mars coordinates" obfuscation, which is offset from
* WGS-84 by roughly 300–800 m depending on where you are.
*
* So this file exists to keep exactly one datum inside the app. It is used at
* two boundaries and nowhere else:
*
* - server/src/nest/maps/providers/amap.provider.ts converts on the way out
* and back in, so a place that reaches the database is always WGS-84.
* - client/src/components/Map/gcj02Crs.ts folds the shift into a Leaflet
* projection, so GCJ-02 raster tiles line up with WGS-84 markers without
* any component having to know which basemap is loaded.
*
* The algorithm is the widely used published approximation (the same one every
* `coordtransform`-style library implements). It is not the state secret itself
* and is accurate to a metre or two, which is well inside the precision a POI
* search result carries. `gcj02ToWgs84` inverts it numerically rather than with
* the common one-shot "subtract the same offset" trick: the offset is a function
* of position, so subtracting it at the wrong position leaves a few metres of
* error, and a round trip through a search result and back into a share link
* would drift visibly.
*/
/** Krasovsky 1940 semi-major axis, the ellipsoid the published offset uses. */
const A = 6378245;
/** Its first eccentricity squared. */
const EE = 0.006_693_421_622_965_943;
const PI = Math.PI;
/**
* True when GCJ-02 does not apply and the coordinate must pass through
* untouched.
*
* Without this every foreign trip in TREK would move: the offset formula is
* happy to evaluate anywhere on earth, so applying it to Paris shifts Paris.
* The bounding box is deliberately the crude one every implementation uses —
* it over-covers, reaching into the sea and into neighbouring countries, but
* erring that way only means a coordinate in the border area gets a shift of a
* few hundred metres applied consistently in both directions, which round-trips
* cleanly. A tighter polygon would risk the far worse failure of converting one
* way and not the other.
*
* Hong Kong, Macau and Taiwan are inside the box. That matches what Amap
* actually serves for them, so it is not an oversight.
*/
export function isOutsideChina(lat: number, lng: number): boolean {
if (!Number.isFinite(lat) || !Number.isFinite(lng)) return true;
return lng < 72.004 || lng > 137.8347 || lat < 0.8293 || lat > 55.8271;
}
function transformLat(x: number, y: number): number {
let ret = -100 + 2 * x + 3 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
ret += ((20 * Math.sin(6 * x * PI) + 20 * Math.sin(2 * x * PI)) * 2) / 3;
ret += ((20 * Math.sin(y * PI) + 40 * Math.sin((y / 3) * PI)) * 2) / 3;
ret += ((160 * Math.sin((y / 12) * PI) + 320 * Math.sin((y * PI) / 30)) * 2) / 3;
return ret;
}
function transformLng(x: number, y: number): number {
let ret = 300 + x + 2 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
ret += ((20 * Math.sin(6 * x * PI) + 20 * Math.sin(2 * x * PI)) * 2) / 3;
ret += ((20 * Math.sin(x * PI) + 40 * Math.sin((x / 3) * PI)) * 2) / 3;
ret += ((150 * Math.sin((x / 12) * PI) + 300 * Math.sin((x / 30) * PI)) * 2) / 3;
return ret;
}
/** The position-dependent offset added to a WGS-84 point to get GCJ-02. */
function offset(lat: number, lng: number): { dLat: number; dLng: number } {
const x = lng - 105;
const y = lat - 35;
let dLat = transformLat(x, y);
let dLng = transformLng(x, y);
const radLat = (lat / 180) * PI;
let magic = Math.sin(radLat);
magic = 1 - EE * magic * magic;
const sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180) / (((A * (1 - EE)) / (magic * sqrtMagic)) * PI);
dLng = (dLng * 180) / ((A / sqrtMagic) * Math.cos(radLat) * PI);
return { dLat, dLng };
}
export interface LatLng {
lat: number;
lng: number;
}
/** WGS-84 → GCJ-02. Outside China the input is returned unchanged. */
export function wgs84ToGcj02(lat: number, lng: number): LatLng {
if (isOutsideChina(lat, lng)) return { lat, lng };
const { dLat, dLng } = offset(lat, lng);
return { lat: lat + dLat, lng: lng + dLng };
}
/**
* GCJ-02 → WGS-84, solved rather than approximated.
*
* The forward offset is a function of the *WGS-84* position, so the usual
* `wgs - (gcj_of_gcj - gcj)` shortcut evaluates it at the wrong point and
* leaves several metres of error. Newton would need the Jacobian of a sum of
* sines; a fixed-point iteration converges just as fast here because the offset
* varies slowly with position, and it cannot diverge. Three or four passes reach
* the double-precision floor; the loop below stops as soon as a pass moves the
* answer by less than ~1e-9° (about 0.1 mm) and is capped so a pathological
* input cannot spin.
*/
export function gcj02ToWgs84(lat: number, lng: number): LatLng {
if (isOutsideChina(lat, lng)) return { lat, lng };
let guessLat = lat;
let guessLng = lng;
for (let i = 0; i < 10; i++) {
const forward = wgs84ToGcj02(guessLat, guessLng);
const errLat = forward.lat - lat;
const errLng = forward.lng - lng;
if (Math.abs(errLat) < 1e-9 && Math.abs(errLng) < 1e-9) break;
guessLat -= errLat;
guessLng -= errLng;
}
return { lat: guessLat, lng: guessLng };
}
/**
* Amap spells a coordinate `lng,lat` in a single string, with six decimals, and
* rejects more than that on some endpoints. Longitude first is the opposite of
* every other coordinate in this codebase, so the ordering lives here once
* instead of at each call site.
*/
export function toAmapLocation(lat: number, lng: number): string {
const gcj = wgs84ToGcj02(lat, lng);
return `${gcj.lng.toFixed(6)},${gcj.lat.toFixed(6)}`;
}
/**
* Parse Amap's `"lng,lat"` back into a WGS-84 pair, or null when the field is
* missing or unparseable — which Amap does do: a POI with no geometry comes
* back with `location: []` rather than with the key absent.
*/
export function fromAmapLocation(location: unknown): LatLng | null {
if (typeof location !== 'string') return null;
const parts = location.split(',');
if (parts.length !== 2) return null;
// Destructured with a default rather than indexed: under noUncheckedIndexedAccess
// an index into a length-checked array is still `string | undefined`.
const [lngText = '', latText = ''] = parts;
const lng = Number.parseFloat(lngText);
const lat = Number.parseFloat(latText);
if (!Number.isFinite(lat) || !Number.isFinite(lng)) return null;
return gcj02ToWgs84(lat, lng);
}
+12
View File
@@ -154,6 +154,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': 'لبيانات الطقس. مجاني من openweathermap.org',
'admin.unsplashKey': 'مفتاح واجهة برمجة تطبيقات Unsplash',
'admin.unsplashKeyHint': 'للبحث عن الصور. مجاني من unsplash.com/developers',
'admin.amapKey': 'مفتاح واجهة برمجة تطبيقات Amap (高德地图)',
'admin.amapKeyHint':
'للبحث عن الأماكن في البر الرئيسي للصين، حيث لا يمكن الوصول إلى Google وتكون بيانات OpenStreetMap شحيحة. يتطلب مفتاحًا من نوع «Web 服务» (خدمة ويب)، وليس مفتاح JS API. يمكن الحصول عليه من console.amap.com.',
'admin.placesProvider.title': 'مزوّد البحث عن الأماكن',
'admin.placesProvider.subtitle':
'الخدمة التي تتولى البحث عن الأماكن والإكمال التلقائي والتفاصيل. «تلقائي» يستخدم Google عند توفر مفتاح Google، ثم Amap، ثم OpenStreetMap.',
'admin.placesProvider.auto': 'تلقائي',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap (高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': 'المزوّد المحدد لا يحتوي على مفتاح واجهة برمجة تطبيقات، لذا يعود البحث عن الأماكن إلى OpenStreetMap.',
'admin.placesProvider.saved': 'تم حفظ مزوّد البحث عن الأماكن',
'admin.validateKey': 'اختبار',
'admin.keyValid': 'متصل',
'admin.keyInvalid': 'غير صالح',
+7
View File
@@ -92,6 +92,9 @@ const places: TranslationStrings = {
'places.loadingDetails': 'جارٍ تحميل تفاصيل المكان…',
'places.osmHint':
'يتم البحث عبر OpenStreetMap (بدون صور أو ساعات عمل أو تقييمات). أضف مفتاح Google API في الإعدادات للحصول على جميع التفاصيل.',
'places.osmActive': 'يتم استخدام OpenStreetMap. مفتاح Google API يضيف التقييمات وساعات العمل.',
'places.osmActiveAmap': 'تجري المشاركة عبر OpenStreetMap. يضيف مفتاح واجهة Amap (高德地图) التقييمات وساعات العمل.',
'places.osmActiveAny': 'تجري المشاركة عبر OpenStreetMap. يضيف مفتاح واجهة Google أو Amap (高德地图) التقييمات وساعات العمل.',
'places.details.title': 'تفاصيل المكان',
'places.details.empty': 'اختر نتيجة لعرض التفاصيل',
'places.details.loading': 'جارٍ تحميل التفاصيل...',
@@ -104,6 +107,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': 'أفرغ حقل الوصف أولًا',
'places.details.facts': 'معلومات مفيدة',
'places.details.nothing': 'لم يتم العثور على شيء لهذا المكان.',
'places.details.noKeyTitle': 'تتوفر تفاصيل أكثر',
'places.details.noKeyHint': 'بدون مفتاح Google API يستخدم هذا التثبيت المصادر الحرة فقط. اطلب من مسؤول TREK إضافة مفتاح للحصول على التقييمات وساعات العمل والصور.',
'places.details.noKeyHintAmap': 'بدون مفتاح واجهة Amap (高德地图) يمكن لهذا المثيل استخدام المصادر المجانية فقط. اطلب من مسؤول TREK إضافة مفتاح للحصول على التقييمات وساعات العمل.',
'places.details.noKeyHintAny': 'بدون مفتاح واجهة Google أو Amap (高德地图) يمكن لهذا المثيل استخدام المصادر المجانية فقط. اطلب من مسؤول TREK إضافة مفتاح للحصول على التقييمات وساعات العمل.',
'places.details.aboutBrand': 'عن السلسلة',
'places.details.aboutBrandNote': 'يصف السلسلة، لا هذا الفرع.',
'places.details.fact.rating': 'التقييم',
+12
View File
@@ -132,6 +132,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': 'Para dados meteorológicos. Grátis em openweathermap.org',
'admin.unsplashKey': 'Chave de API do Unsplash',
'admin.unsplashKeyHint': 'Para busca de imagens. Grátis em unsplash.com/developers',
'admin.amapKey': 'Chave de API do Amap (高德地图)',
'admin.amapKeyHint':
'Para a busca de lugares na China continental, onde o Google é inacessível e o OpenStreetMap tem poucos dados. Exige uma chave do tipo "Web 服务" (serviço web), não uma chave da API JS. Obtenha em console.amap.com.',
'admin.placesProvider.title': 'Provedor de busca de lugares',
'admin.placesProvider.subtitle':
'Qual serviço responde à busca de lugares, ao autocompletar e aos detalhes. Automático usa o Google quando há uma chave do Google configurada, depois o Amap e depois o OpenStreetMap.',
'admin.placesProvider.auto': 'Automático',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap (高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': 'O provedor selecionado não tem nenhuma chave de API configurada, então a busca de lugares volta para o OpenStreetMap.',
'admin.placesProvider.saved': 'Provedor de busca de lugares salvo',
'admin.validateKey': 'Testar',
'admin.keyValid': 'Conectado',
'admin.keyInvalid': 'Inválida',
+7
View File
@@ -92,6 +92,9 @@ const places: TranslationStrings = {
'places.loadingDetails': 'Carregando detalhes do lugar…',
'places.osmHint':
'Busca via OpenStreetMap (sem fotos, horários ou avaliações). Adicione uma chave Google nas configurações para detalhes completos.',
'places.osmActive': 'Usando o OpenStreetMap. Uma chave de API do Google adiciona avaliações e horários.',
'places.osmActiveAmap': 'Usando o OpenStreetMap. Uma chave de API do Amap (高德地图) adiciona avaliações e horários de funcionamento.',
'places.osmActiveAny': 'Usando o OpenStreetMap. Uma chave de API do Google ou do Amap (高德地图) adiciona avaliações e horários de funcionamento.',
'places.details.title': 'Detalhes do lugar',
'places.details.empty': 'Escolha um resultado para ver mais',
'places.details.loading': 'Carregando detalhes...',
@@ -104,6 +107,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': 'Esvazie primeiro o campo de descrição',
'places.details.facts': 'Bom saber',
'places.details.nothing': 'Nada encontrado para este lugar.',
'places.details.noKeyTitle': 'Mais detalhes disponíveis',
'places.details.noKeyHint': 'Sem uma chave de API do Google, esta instância usa apenas fontes livres. Peça ao administrador do TREK para adicionar uma para avaliações, horários e fotos.',
'places.details.noKeyHintAmap': 'Sem uma chave de API do Amap (高德地图), esta instância só pode usar fontes gratuitas. Peça ao administrador do TREK para adicionar uma, para ter avaliações e horários.',
'places.details.noKeyHintAny': 'Sem uma chave de API do Google ou do Amap (高德地图), esta instância só pode usar fontes gratuitas. Peça ao administrador do TREK para adicionar uma, para ter avaliações e horários.',
'places.details.aboutBrand': 'Sobre a rede',
'places.details.aboutBrandNote': 'Descreve a rede, não esta unidade.',
'places.details.fact.rating': 'Avaliação',
+12
View File
@@ -132,6 +132,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': 'Pro data o počasí. Zdarma na openweathermap.org',
'admin.unsplashKey': 'Klíč API Unsplash',
'admin.unsplashKeyHint': 'Pro vyhledávání obrázků. Zdarma na unsplash.com/developers',
'admin.amapKey': 'API klíč Amap (高德地图)',
'admin.amapKeyHint':
'Pro hledání míst v kontinentální Číně, kde Google není dostupný a OpenStreetMap má málo dat. Vyžaduje klíč typu „Web 服务" (webová služba), nikoli klíč JS API. Získáte na console.amap.com.',
'admin.placesProvider.title': 'Poskytovatel hledání míst',
'admin.placesProvider.subtitle':
'Která služba obsluhuje hledání míst, našeptávač a podrobnosti. Automaticky použije Google, pokud je nastaven klíč Google, poté Amap a poté OpenStreetMap.',
'admin.placesProvider.auto': 'Automaticky',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap (高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': 'Pro vybraného poskytovatele není nastaven API klíč, hledání míst proto přejde na OpenStreetMap.',
'admin.placesProvider.saved': 'Poskytovatel hledání míst uložen',
'admin.validateKey': 'Testovat',
'admin.keyValid': 'Připojeno',
'admin.keyInvalid': 'Neplatný',
+7
View File
@@ -92,6 +92,9 @@ const places: TranslationStrings = {
'places.loadingDetails': 'Načítání podrobností místa…',
'places.osmHint':
'Používáte hledání přes OpenStreetMap (bez fotek a hodnocení). Pro plné detaily přidejte Google API klíč v nastavení.',
'places.osmActive': 'Používá se OpenStreetMap. Klíč Google API přidá hodnocení a otevírací dobu.',
'places.osmActiveAmap': 'Používá se OpenStreetMap. Klíč API Amap (高德地图) přidá hodnocení a otevírací dobu.',
'places.osmActiveAny': 'Používá se OpenStreetMap. Klíč API Google nebo Amap (高德地图) přidá hodnocení a otevírací dobu.',
'places.details.title': 'Podrobnosti místa',
'places.details.empty': 'Vyber výsledek a zobraz detaily',
'places.details.loading': 'Načítání podrobností...',
@@ -104,6 +107,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': 'Nejdřív vyprázdni pole popisu',
'places.details.facts': 'Dobré vědět',
'places.details.nothing': 'Pro toto místo se nic nenašlo.',
'places.details.noKeyTitle': 'K dispozici je více podrobností',
'places.details.noKeyHint': 'Bez klíče Google API používá tato instance jen volné zdroje. Požádejte správce TREK o jeho přidání pro hodnocení, otevírací dobu a fotografie.',
'places.details.noKeyHintAmap': 'Bez klíče API Amap (高德地图) může tato instance používat jen bezplatné zdroje. Požádejte správce TREK, aby klíč přidal — přibydou hodnocení a otevírací doba.',
'places.details.noKeyHintAny': 'Bez klíče API Google nebo Amap (高德地图) může tato instance používat jen bezplatné zdroje. Požádejte správce TREK, aby klíč přidal — přibydou hodnocení a otevírací doba.',
'places.details.aboutBrand': 'O řetězci',
'places.details.aboutBrandNote': 'Popisuje řetězec, ne tuto pobočku.',
'places.details.fact.rating': 'Hodnocení',
+12
View File
@@ -134,6 +134,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': 'Für Wetterdaten. Kostenlos unter openweathermap.org',
'admin.unsplashKey': 'Unsplash-API-Schlüssel',
'admin.unsplashKeyHint': 'Für die Bildsuche. Kostenlos unter unsplash.com/developers',
'admin.amapKey': 'Amap (高德地图) API-Key',
'admin.amapKeyHint':
'Für die Ortssuche in Festlandchina, wo Google nicht erreichbar ist und OpenStreetMap kaum Daten hat. Benötigt einen Key vom Typ „Web 服务" (Webdienst), nicht einen JS-API-Key. Erhältlich auf console.amap.com.',
'admin.placesProvider.title': 'Anbieter für die Ortssuche',
'admin.placesProvider.subtitle':
'Welcher Dienst Ortssuche, Vorschläge und Details beantwortet. Automatisch nutzt Google, wenn ein Google-Key hinterlegt ist, dann Amap, dann OpenStreetMap.',
'admin.placesProvider.auto': 'Automatisch',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap (高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': 'Für den gewählten Anbieter ist kein API-Key hinterlegt, die Ortssuche fällt daher auf OpenStreetMap zurück.',
'admin.placesProvider.saved': 'Anbieter für die Ortssuche gespeichert',
'admin.validateKey': 'Test',
'admin.keyValid': 'Verbunden',
'admin.keyInvalid': 'Ungültig',
+7
View File
@@ -92,6 +92,9 @@ const places: TranslationStrings = {
'places.loadingDetails': 'Ortsdetails werden geladen…',
'places.osmHint':
'OpenStreetMap-Suche aktiv (ohne Bilder, Öffnungszeiten, Bewertungen). Für erweiterte Daten Google API Key in den Einstellungen hinterlegen.',
'places.osmActive': 'OpenStreetMap wird genutzt. Ein Google-API-Key ergänzt Bewertungen und Öffnungszeiten.',
'places.osmActiveAmap': 'OpenStreetMap ist aktiv. Ein Amap-API-Key (高德地图) ergänzt Bewertungen und Öffnungszeiten.',
'places.osmActiveAny': 'OpenStreetMap ist aktiv. Ein Google- oder Amap-API-Key (高德地图) ergänzt Bewertungen und Öffnungszeiten.',
'places.details.title': 'Ortsdetails',
'places.details.empty': 'Wähle ein Ergebnis für Details',
'places.details.loading': 'Details werden geladen...',
@@ -104,6 +107,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': 'Erst das Beschreibungsfeld leeren',
'places.details.facts': 'Gut zu wissen',
'places.details.nothing': 'Zu diesem Ort wurde nichts gefunden.',
'places.details.noKeyTitle': 'Mehr Details möglich',
'places.details.noKeyHint': 'Ohne Google-API-Key nutzt diese Instanz nur freie Quellen. Wende dich an deine TREK-Administration, um Bewertungen, Öffnungszeiten und Fotos freizuschalten.',
'places.details.noKeyHintAmap': 'Ohne Amap-API-Key (高德地图) kann diese Instanz nur freie Quellen nutzen. Bitte die TREK-Administration, einen Key für Bewertungen und Öffnungszeiten hinzuzufügen.',
'places.details.noKeyHintAny': 'Ohne Google- oder Amap-API-Key (高德地图) kann diese Instanz nur freie Quellen nutzen. Bitte die TREK-Administration, einen Key für Bewertungen und Öffnungszeiten hinzuzufügen.',
'places.details.aboutBrand': 'Über die Kette',
'places.details.aboutBrandNote': 'Beschreibt die Kette, nicht diese Filiale.',
'places.details.fact.rating': 'Bewertung',
+12
View File
@@ -174,6 +174,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': 'For weather data. Free at openweathermap.org',
'admin.unsplashKey': 'Unsplash API Key',
'admin.unsplashKeyHint': 'For image search. Free at unsplash.com/developers',
'admin.amapKey': 'Amap (高德地图) API Key',
'admin.amapKeyHint':
'For place search inside mainland China, where Google is unreachable and OpenStreetMap coverage is thin. Needs a "Web 服务" (web service) key, not a JS API key. Get one at console.amap.com.',
'admin.placesProvider.title': 'Place search provider',
'admin.placesProvider.subtitle':
'Which service answers place search, autocomplete and details. Automatic uses Google when a Google key is configured, then Amap, then OpenStreetMap.',
'admin.placesProvider.auto': 'Automatic',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap (高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': 'The selected provider has no API key configured, so place search falls back to OpenStreetMap.',
'admin.placesProvider.saved': 'Place search provider saved',
'admin.validateKey': 'Test',
'admin.keyValid': 'Connected',
'admin.keyInvalid': 'Invalid',
+7
View File
@@ -93,6 +93,9 @@ const places: TranslationStrings = {
'places.loadingDetails': 'Loading place details…',
'places.osmHint':
'Using OpenStreetMap search (no photos, opening hours, or ratings). Add a Google API key in settings for full details.',
'places.osmActive': 'Using OpenStreetMap. A Google API key adds ratings and opening hours.',
'places.osmActiveAmap': 'Using OpenStreetMap. An Amap (高德地图) API key adds ratings and opening hours.',
'places.osmActiveAny': 'Using OpenStreetMap. A Google or Amap (高德地图) API key adds ratings and opening hours.',
'places.details.title': 'Place details',
'places.details.empty': 'Pick a result to see more',
'places.details.loading': 'Loading details...',
@@ -105,6 +108,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': 'Clear the description field first',
'places.details.facts': 'Good to know',
'places.details.nothing': 'Nothing found for this place.',
'places.details.noKeyTitle': 'More detail is available',
'places.details.noKeyHint': 'Without a Google API key this instance can only use free sources. Ask your TREK administrator to add one for ratings, opening hours and photos.',
'places.details.noKeyHintAmap': 'Without an Amap (高德地图) API key this instance can only use free sources. Ask your TREK administrator to add one for ratings and opening hours.',
'places.details.noKeyHintAny': 'Without a Google or Amap (高德地图) API key this instance can only use free sources. Ask your TREK administrator to add one for ratings and opening hours.',
'places.details.aboutBrand': 'About the chain',
'places.details.aboutBrandNote': 'This describes the chain, not this branch.',
'places.details.fact.rating': 'Rating',
+12
View File
@@ -134,6 +134,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': 'Para datos meteorológicos. Gratis en openweathermap.org',
'admin.unsplashKey': 'Clave de API de Unsplash',
'admin.unsplashKeyHint': 'Para la búsqueda de imágenes. Gratis en unsplash.com/developers',
'admin.amapKey': 'Clave de API de Amap (高德地图)',
'admin.amapKeyHint':
'Para la búsqueda de lugares en China continental, donde Google no es accesible y OpenStreetMap apenas tiene datos. Requiere una clave de tipo «Web 服务» (servicio web), no una clave de la API de JS. Consíguela en console.amap.com.',
'admin.placesProvider.title': 'Proveedor de búsqueda de lugares',
'admin.placesProvider.subtitle':
'Qué servicio responde a la búsqueda de lugares, el autocompletado y los detalles. Automático usa Google si hay una clave de Google configurada, luego Amap y luego OpenStreetMap.',
'admin.placesProvider.auto': 'Automático',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap (高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': 'El proveedor seleccionado no tiene ninguna clave de API configurada, así que la búsqueda de lugares recurre a OpenStreetMap.',
'admin.placesProvider.saved': 'Proveedor de búsqueda de lugares guardado',
'admin.validateKey': 'Probar',
'admin.keyValid': 'Conectado',
'admin.keyInvalid': 'No válida',
+7
View File
@@ -92,6 +92,9 @@ const places: TranslationStrings = {
'places.loadingDetails': 'Cargando detalles del lugar…',
'places.osmHint':
'Usando búsqueda con OpenStreetMap (sin fotos, horarios ni valoraciones). Añade una clave API de Google en Ajustes para obtener todos los detalles.',
'places.osmActive': 'Se usa OpenStreetMap. Una clave de API de Google añade valoraciones y horarios.',
'places.osmActiveAmap': 'Usando OpenStreetMap. Una clave de API de Amap (高德地图) añade valoraciones y horarios.',
'places.osmActiveAny': 'Usando OpenStreetMap. Una clave de API de Google o de Amap (高德地图) añade valoraciones y horarios.',
'places.details.title': 'Detalles del lugar',
'places.details.empty': 'Elige un resultado para ver más',
'places.details.loading': 'Cargando detalles...',
@@ -104,6 +107,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': 'Vacía primero el campo de descripción',
'places.details.facts': 'Bueno saber',
'places.details.nothing': 'No se encontró nada para este lugar.',
'places.details.noKeyTitle': 'Hay más detalles disponibles',
'places.details.noKeyHint': 'Sin una clave de API de Google, esta instancia solo usa fuentes libres. Pide a tu administrador de TREK que añada una para valoraciones, horarios y fotos.',
'places.details.noKeyHintAmap': 'Sin una clave de API de Amap (高德地图) esta instancia solo puede usar fuentes gratuitas. Pide al administrador de TREK que añada una para valoraciones y horarios.',
'places.details.noKeyHintAny': 'Sin una clave de API de Google o de Amap (高德地图) esta instancia solo puede usar fuentes gratuitas. Pide al administrador de TREK que añada una para valoraciones y horarios.',
'places.details.aboutBrand': 'Sobre la cadena',
'places.details.aboutBrandNote': 'Describe la cadena, no este local.',
'places.details.fact.rating': 'Valoración',
+12
View File
@@ -133,6 +133,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': 'Pour les données météo. Gratuit sur openweathermap.org',
'admin.unsplashKey': 'Clé API Unsplash',
'admin.unsplashKeyHint': 'Pour la recherche d’images. Gratuit sur unsplash.com/developers',
'admin.amapKey': 'Clé API Amap (高德地图)',
'admin.amapKeyHint':
'Pour la recherche de lieux en Chine continentale, où Google est inaccessible et où OpenStreetMap contient très peu de données. Nécessite une clé de type « Web 服务 » (service web), pas une clé d’API JS. À obtenir sur console.amap.com.',
'admin.placesProvider.title': 'Fournisseur de recherche de lieux',
'admin.placesProvider.subtitle':
'Quel service répond à la recherche de lieux, à l’autocomplétion et aux détails. Automatique utilise Google si une clé Google est configurée, puis Amap, puis OpenStreetMap.',
'admin.placesProvider.auto': 'Automatique',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap (高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': 'Aucune clé API n’est configurée pour le fournisseur sélectionné : la recherche de lieux se replie donc sur OpenStreetMap.',
'admin.placesProvider.saved': 'Fournisseur de recherche de lieux enregistré',
'admin.validateKey': 'Tester',
'admin.keyValid': 'Connecté',
'admin.keyInvalid': 'Invalide',
+7
View File
@@ -92,6 +92,9 @@ const places: TranslationStrings = {
'places.loadingDetails': 'Chargement des détails du lieu…',
'places.osmHint':
'Recherche via OpenStreetMap (pas de photos, horaires ni notes). Ajoutez une clé API Google dans les paramètres pour plus de détails.',
'places.osmActive': 'OpenStreetMap est utilisé. Une clé API Google ajoute notes et horaires.',
'places.osmActiveAmap': 'OpenStreetMap est utilisé. Une clé API Amap (高德地图) ajoute notes et horaires d’ouverture.',
'places.osmActiveAny': 'OpenStreetMap est utilisé. Une clé API Google ou Amap (高德地图) ajoute notes et horaires d’ouverture.',
'places.details.title': 'Détails du lieu',
'places.details.empty': 'Choisis un résultat pour en voir plus',
'places.details.loading': 'Chargement des détails...',
@@ -104,6 +107,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': "Videz d'abord le champ description",
'places.details.facts': 'Bon à savoir',
'places.details.nothing': 'Rien trouvé pour ce lieu.',
'places.details.noKeyTitle': 'Plus de détails disponibles',
'places.details.noKeyHint': 'Sans clé API Google, cette instance n\'utilise que des sources libres. Demandez à votre administrateur TREK d\'en ajouter une pour les avis, les horaires et les photos.',
'places.details.noKeyHintAmap': 'Sans clé API Amap (高德地图), cette instance ne peut utiliser que des sources gratuites. Demandez à l’administrateur TREK d’en ajouter une pour les notes et les horaires.',
'places.details.noKeyHintAny': 'Sans clé API Google ou Amap (高德地图), cette instance ne peut utiliser que des sources gratuites. Demandez à l’administrateur TREK d’en ajouter une pour les notes et les horaires.',
'places.details.aboutBrand': 'À propos de la chaîne',
'places.details.aboutBrandNote': 'Décrit la chaîne, pas cet établissement.',
'places.details.fact.rating': 'Note',
+12
View File
@@ -179,6 +179,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': 'Για δεδομένα καιρού. Δωρεάν στο openweathermap.org',
'admin.unsplashKey': 'Κλειδί API Unsplash',
'admin.unsplashKeyHint': 'Για αναζήτηση εικόνων. Δωρεάν στο unsplash.com/developers',
'admin.amapKey': 'Κλειδί API του Amap (高德地图)',
'admin.amapKeyHint':
'Για αναζήτηση τοποθεσιών στην ηπειρωτική Κίνα, όπου το Google δεν είναι προσβάσιμο και το OpenStreetMap έχει ελάχιστα δεδομένα. Χρειάζεται κλειδί τύπου «Web 服务» (υπηρεσία web), όχι κλειδί JS API. Διαθέσιμο στο console.amap.com.',
'admin.placesProvider.title': 'Πάροχος αναζήτησης τοποθεσιών',
'admin.placesProvider.subtitle':
'Ποια υπηρεσία απαντά στην αναζήτηση τοποθεσιών, στις προτάσεις και στις λεπτομέρειες. Το «Αυτόματα» χρησιμοποιεί το Google όταν υπάρχει κλειδί Google, μετά το Amap και μετά το OpenStreetMap.',
'admin.placesProvider.auto': 'Αυτόματα',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap (高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': 'Ο επιλεγμένος πάροχος δεν έχει ρυθμισμένο κλειδί API, οπότε η αναζήτηση τοποθεσιών επιστρέφει στο OpenStreetMap.',
'admin.placesProvider.saved': 'Ο πάροχος αναζήτησης τοποθεσιών αποθηκεύτηκε',
'admin.validateKey': 'Δοκιμή',
'admin.keyValid': 'Συνδέθηκε',
'admin.keyInvalid': 'Μη έγκυρο',
+7
View File
@@ -92,6 +92,9 @@ const places: TranslationStrings = {
'places.loadingDetails': 'Φόρτωση λεπτομερειών μέρους…',
'places.osmHint':
'Χρήση αναζήτησης OpenStreetMap (χωρίς φωτογραφίες, ώρες λειτουργίας ή αξιολογήσεις). Προσθέστε ένα κλειδί Google API στις ρυθμίσεις για πλήρεις λεπτομέρειες.',
'places.osmActive': 'Χρησιμοποιείται το OpenStreetMap. Ένα κλειδί Google API προσθέτει αξιολογήσεις και ωράρια.',
'places.osmActiveAmap': 'Χρησιμοποιείται το OpenStreetMap. Ένα κλειδί API του Amap (高德地图) προσθέτει βαθμολογίες και ώρες λειτουργίας.',
'places.osmActiveAny': 'Χρησιμοποιείται το OpenStreetMap. Ένα κλειδί API Google ή Amap (高德地图) προσθέτει βαθμολογίες και ώρες λειτουργίας.',
'places.details.title': 'Λεπτομέρειες τοποθεσίας',
'places.details.empty': 'Επίλεξε ένα αποτέλεσμα για περισσότερα',
'places.details.loading': 'Φόρτωση λεπτομερειών...',
@@ -104,6 +107,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': 'Άδειασε πρώτα το πεδίο περιγραφής',
'places.details.facts': 'Καλό να ξέρεις',
'places.details.nothing': 'Δεν βρέθηκε τίποτα για αυτήν την τοποθεσία.',
'places.details.noKeyTitle': 'Διατίθενται περισσότερες λεπτομέρειες',
'places.details.noKeyHint': 'Χωρίς κλειδί Google API, αυτή η εγκατάσταση χρησιμοποιεί μόνο ελεύθερες πηγές. Ζητήστε από τον διαχειριστή TREK να προσθέσει ένα για βαθμολογίες, ώρες λειτουργίας και φωτογραφίες.',
'places.details.noKeyHintAmap': 'Χωρίς κλειδί API Amap (高德地图) αυτή η εγκατάσταση μπορεί να χρησιμοποιεί μόνο δωρεάν πηγές. Ζητήστε από τον διαχειριστή TREK να προσθέσει ένα για βαθμολογίες και ώρες λειτουργίας.',
'places.details.noKeyHintAny': 'Χωρίς κλειδί API Google ή Amap (高德地图) αυτή η εγκατάσταση μπορεί να χρησιμοποιεί μόνο δωρεάν πηγές. Ζητήστε από τον διαχειριστή TREK να προσθέσει ένα για βαθμολογίες και ώρες λειτουργίας.',
'places.details.aboutBrand': 'Σχετικά με την αλυσίδα',
'places.details.aboutBrandNote': 'Περιγράφει την αλυσίδα, όχι αυτό το κατάστημα.',
'places.details.fact.rating': 'Βαθμολογία',
+12
View File
@@ -133,6 +133,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': 'Időjárás adatokhoz. Ingyenes: openweathermap.org',
'admin.unsplashKey': 'Unsplash API-kulcs',
'admin.unsplashKeyHint': 'Képkereséshez. Ingyenes: unsplash.com/developers',
'admin.amapKey': 'Amap (高德地图) API-kulcs',
'admin.amapKeyHint':
'Helykereséshez Kína szárazföldi részén, ahol a Google nem érhető el, az OpenStreetMap adatai pedig hiányosak. „Web 服务" (webszolgáltatás) típusú kulcs kell hozzá, nem JS API-kulcs. A console.amap.com oldalon kérhető.',
'admin.placesProvider.title': 'Helykeresési szolgáltató',
'admin.placesProvider.subtitle':
'Melyik szolgáltatás válaszol a helykeresésre, a javaslatokra és a részletekre. Az automatikus a Google-t használja, ha van Google-kulcs, utána az Amapot, végül az OpenStreetMapet.',
'admin.placesProvider.auto': 'Automatikus',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap (高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': 'A kiválasztott szolgáltatóhoz nincs API-kulcs beállítva, ezért a helykeresés az OpenStreetMapre esik vissza.',
'admin.placesProvider.saved': 'Helykeresési szolgáltató elmentve',
'admin.validateKey': 'Teszt',
'admin.keyValid': 'Csatlakozva',
'admin.keyInvalid': 'Érvénytelen',
+7
View File
@@ -92,6 +92,9 @@ const places: TranslationStrings = {
'places.loadingDetails': 'Hely adatainak betöltése…',
'places.osmHint':
'OpenStreetMap keresés aktív (képek, nyitvatartás és értékelések nélkül). Bővített adatokhoz add meg a Google API kulcsot a beállításokban.',
'places.osmActive': 'Az OpenStreetMap van használatban. Egy Google API-kulcs értékeléseket és nyitvatartást ad hozzá.',
'places.osmActiveAmap': 'OpenStreetMap használatban. Egy Amap (高德地图) API-kulcs értékeléseket és nyitvatartást ad.',
'places.osmActiveAny': 'OpenStreetMap használatban. Egy Google vagy Amap (高德地图) API-kulcs értékeléseket és nyitvatartást ad.',
'places.details.title': 'Hely részletei',
'places.details.empty': 'Válassz egy találatot a részletekhez',
'places.details.loading': 'Részletek betöltése...',
@@ -104,6 +107,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': 'Előbb ürítsd ki a leírás mezőt',
'places.details.facts': 'Jó tudni',
'places.details.nothing': 'Ehhez a helyhez nem található semmi.',
'places.details.noKeyTitle': 'További részletek érhetők el',
'places.details.noKeyHint': 'Google API-kulcs nélkül ez a példány csak szabad forrásokat használ. Kérd a TREK rendszergazdáját, hogy adjon hozzá egyet az értékelésekhez, nyitvatartáshoz és fotókhoz.',
'places.details.noKeyHintAmap': 'Amap (高德地图) API-kulcs nélkül ez a példány csak ingyenes forrásokat használhat. Kérd a TREK rendszergazdáját, hogy adjon hozzá egyet értékelésekhez és nyitvatartáshoz.',
'places.details.noKeyHintAny': 'Google vagy Amap (高德地图) API-kulcs nélkül ez a példány csak ingyenes forrásokat használhat. Kérd a TREK rendszergazdáját, hogy adjon hozzá egyet értékelésekhez és nyitvatartáshoz.',
'places.details.aboutBrand': 'A láncról',
'places.details.aboutBrandNote': 'A láncot írja le, nem ezt az egységet.',
'places.details.fact.rating': 'Értékelés',
+12
View File
@@ -175,6 +175,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': 'Untuk data cuaca. Gratis di openweathermap.org',
'admin.unsplashKey': 'Kunci API Unsplash',
'admin.unsplashKeyHint': 'Untuk pencarian gambar. Gratis di unsplash.com/developers',
'admin.amapKey': 'Kunci API Amap (高德地图)',
'admin.amapKeyHint':
'Untuk pencarian tempat di Tiongkok daratan, tempat Google tidak dapat diakses dan data OpenStreetMap sangat sedikit. Perlu kunci jenis "Web 服务" (layanan web), bukan kunci JS API. Dapatkan di console.amap.com.',
'admin.placesProvider.title': 'Penyedia pencarian tempat',
'admin.placesProvider.subtitle':
'Layanan mana yang menangani pencarian tempat, saran otomatis, dan detail. Otomatis memakai Google jika kunci Google tersedia, lalu Amap, lalu OpenStreetMap.',
'admin.placesProvider.auto': 'Otomatis',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap (高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': 'Penyedia yang dipilih belum memiliki kunci API, sehingga pencarian tempat kembali ke OpenStreetMap.',
'admin.placesProvider.saved': 'Penyedia pencarian tempat disimpan',
'admin.validateKey': 'Uji',
'admin.keyValid': 'Terhubung',
'admin.keyInvalid': 'Tidak valid',
+7
View File
@@ -91,6 +91,9 @@ const places: TranslationStrings = {
'places.loadingDetails': 'Memuat detail tempat…',
'places.osmHint':
'Menggunakan pencarian OpenStreetMap (tanpa foto, jam buka, atau penilaian). Tambahkan Google API key di pengaturan untuk detail lengkap.',
'places.osmActive': 'Menggunakan OpenStreetMap. Kunci API Google menambahkan rating dan jam buka.',
'places.osmActiveAmap': 'Menggunakan OpenStreetMap. Kunci API Amap (高德地图) menambahkan rating dan jam buka.',
'places.osmActiveAny': 'Menggunakan OpenStreetMap. Kunci API Google atau Amap (高德地图) menambahkan rating dan jam buka.',
'places.details.title': 'Detail tempat',
'places.details.empty': 'Pilih hasil untuk melihat detail',
'places.details.loading': 'Memuat detail...',
@@ -103,6 +106,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': 'Kosongkan dulu kolom deskripsi',
'places.details.facts': 'Perlu diketahui',
'places.details.nothing': 'Tidak ada yang ditemukan untuk tempat ini.',
'places.details.noKeyTitle': 'Tersedia detail lebih lanjut',
'places.details.noKeyHint': 'Tanpa kunci API Google, instans ini hanya memakai sumber bebas. Minta administrator TREK menambahkannya untuk rating, jam buka, dan foto.',
'places.details.noKeyHintAmap': 'Tanpa kunci API Amap (高德地图), instansi ini hanya bisa memakai sumber gratis. Minta administrator TREK menambahkannya untuk rating dan jam buka.',
'places.details.noKeyHintAny': 'Tanpa kunci API Google atau Amap (高德地图), instansi ini hanya bisa memakai sumber gratis. Minta administrator TREK menambahkannya untuk rating dan jam buka.',
'places.details.aboutBrand': 'Tentang jaringan',
'places.details.aboutBrandNote': 'Menjelaskan jaringannya, bukan cabang ini.',
'places.details.fact.rating': 'Peringkat',
+12
View File
@@ -133,6 +133,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': 'Per i dati meteo. Gratuita su openweathermap.org',
'admin.unsplashKey': 'Chiave API Unsplash',
'admin.unsplashKeyHint': 'Per la ricerca di immagini. Gratuita su unsplash.com/developers',
'admin.amapKey': 'Chiave API Amap (高德地图)',
'admin.amapKeyHint':
'Per la ricerca di luoghi nella Cina continentale, dove Google non è raggiungibile e OpenStreetMap ha pochi dati. Serve una chiave di tipo «Web 服务» (servizio web), non una chiave API JS. Si ottiene su console.amap.com.',
'admin.placesProvider.title': 'Provider per la ricerca di luoghi',
'admin.placesProvider.subtitle':
'Quale servizio risponde a ricerca di luoghi, completamento automatico e dettagli. Automatico usa Google se è configurata una chiave Google, poi Amap, poi OpenStreetMap.',
'admin.placesProvider.auto': 'Automatico',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap (高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': 'Il provider selezionato non ha alcuna chiave API configurata, quindi la ricerca di luoghi ripiega su OpenStreetMap.',
'admin.placesProvider.saved': 'Provider per la ricerca di luoghi salvato',
'admin.validateKey': 'Testa',
'admin.keyValid': 'Connessa',
'admin.keyInvalid': 'Non valida',
+7
View File
@@ -92,6 +92,9 @@ const places: TranslationStrings = {
'places.loadingDetails': 'Caricamento dettagli del luogo…',
'places.osmHint':
'Uso della ricerca OpenStreetMap (senza foto, orari di apertura o valutazioni). Aggiungi una chiave API Google nelle impostazioni per i dettagli completi.',
'places.osmActive': 'Si usa OpenStreetMap. Una chiave API Google aggiunge valutazioni e orari.',
'places.osmActiveAmap': 'Uso OpenStreetMap. Una chiave API Amap (高德地图) aggiunge valutazioni e orari.',
'places.osmActiveAny': 'Uso OpenStreetMap. Una chiave API Google o Amap (高德地图) aggiunge valutazioni e orari.',
'places.details.title': 'Dettagli del luogo',
'places.details.empty': 'Scegli un risultato per saperne di più',
'places.details.loading': 'Caricamento dettagli...',
@@ -104,6 +107,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': 'Svuota prima il campo descrizione',
'places.details.facts': 'Da sapere',
'places.details.nothing': 'Nessun risultato per questo luogo.',
'places.details.noKeyTitle': 'Sono disponibili più dettagli',
'places.details.noKeyHint': 'Senza una chiave API di Google questa istanza usa solo fonti libere. Chiedi all\'amministratore di TREK di aggiungerne una per valutazioni, orari e foto.',
'places.details.noKeyHintAmap': 'Senza una chiave API Amap (高德地图) questa istanza può usare solo fonti gratuite. Chiedi all’amministratore TREK di aggiungerne una per valutazioni e orari.',
'places.details.noKeyHintAny': 'Senza una chiave API Google o Amap (高德地图) questa istanza può usare solo fonti gratuite. Chiedi all’amministratore TREK di aggiungerne una per valutazioni e orari.',
'places.details.aboutBrand': 'Sulla catena',
'places.details.aboutBrandNote': 'Descrive la catena, non questa sede.',
'places.details.fact.rating': 'Valutazione',
+12
View File
@@ -167,6 +167,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': '天気データ用。openweathermap.org で無料',
'admin.unsplashKey': 'Unsplash APIキー',
'admin.unsplashKeyHint': '画像検索用。unsplash.com/developers で無料',
'admin.amapKey': 'Amap(高德地图)API キー',
'admin.amapKeyHint':
'Google に接続できず OpenStreetMap のデータも少ない中国本土での地点検索用です。JS API キーではなく「Web 服务」(Web サービス)タイプのキーが必要です。console.amap.com で取得できます。',
'admin.placesProvider.title': '地点検索のプロバイダー',
'admin.placesProvider.subtitle':
'地点検索・入力候補・詳細をどのサービスが担当するか。自動は、Google キーが設定されていれば Google、次に Amap、次に OpenStreetMap を使います。',
'admin.placesProvider.auto': '自動',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap(高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': '選択したプロバイダーに API キーが設定されていないため、地点検索は OpenStreetMap にフォールバックします。',
'admin.placesProvider.saved': '地点検索のプロバイダーを保存しました',
'admin.validateKey': 'テスト',
'admin.keyValid': '接続済み',
'admin.keyInvalid': '無効',
+7
View File
@@ -92,6 +92,9 @@ const places: TranslationStrings = {
'places.loadingDetails': '詳細を読み込み中…',
'places.osmHint':
'OpenStreetMapで検索しています(写真・営業時間・評価なし)。設定でGoogle APIキーを追加すると詳細が表示されます。',
'places.osmActive': 'OpenStreetMapを使用中。Google APIキーで評価と営業時間が追加されます。',
'places.osmActiveAmap': 'OpenStreetMap を使用中です。Amap(高德地图)の API キーを追加すると評価や営業時間が表示されます。',
'places.osmActiveAny': 'OpenStreetMap を使用中です。Google または Amap(高德地图)の API キーを追加すると評価や営業時間が表示されます。',
'places.details.title': '場所の詳細',
'places.details.empty': '検索結果を選ぶと詳細が表示されます',
'places.details.loading': '詳細を読み込み中...',
@@ -104,6 +107,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': '先に説明欄を空にしてください',
'places.details.facts': '知っておくと便利',
'places.details.nothing': 'この場所の情報は見つかりませんでした。',
'places.details.noKeyTitle': 'さらに詳しい情報を表示できます',
'places.details.noKeyHint': 'Google API キーがない場合、このインスタンスは自由に使えるソースのみを利用します。評価・営業時間・写真のために、TREK の管理者にキーの追加を依頼してください。',
'places.details.noKeyHintAmap': 'Amap(高德地图)の API キーがない場合、このサーバーは無料のソースのみ使用できます。評価や営業時間のために TREK 管理者にキーの追加を依頼してください。',
'places.details.noKeyHintAny': 'Google または Amap(高德地图)の API キーがない場合、このサーバーは無料のソースのみ使用できます。評価や営業時間のために TREK 管理者にキーの追加を依頼してください。',
'places.details.aboutBrand': 'チェーンについて',
'places.details.aboutBrandNote': 'この店舗ではなくチェーン全体の説明です。',
'places.details.fact.rating': '評価',
+12
View File
@@ -172,6 +172,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': '날씨 데이터용. openweathermap.org에서 무료 발급',
'admin.unsplashKey': 'Unsplash API 키',
'admin.unsplashKeyHint': '이미지 검색용. unsplash.com/developers에서 무료 발급',
'admin.amapKey': 'Amap(高德地图) API 키',
'admin.amapKeyHint':
'Google에 접속할 수 없고 OpenStreetMap 데이터도 부족한 중국 본토에서 장소를 검색할 때 사용합니다. JS API 키가 아니라 "Web 服务"(웹 서비스) 유형의 키가 필요합니다. console.amap.com에서 발급받을 수 있습니다.',
'admin.placesProvider.title': '장소 검색 제공자',
'admin.placesProvider.subtitle':
'장소 검색, 자동 완성, 상세 정보를 어느 서비스가 처리할지 결정합니다. 자동은 Google 키가 있으면 Google을, 그다음 Amap을, 그다음 OpenStreetMap을 사용합니다.',
'admin.placesProvider.auto': '자동',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap(高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': '선택한 제공자에 API 키가 설정되어 있지 않아 장소 검색이 OpenStreetMap으로 대체됩니다.',
'admin.placesProvider.saved': '장소 검색 제공자를 저장했습니다',
'admin.validateKey': '테스트',
'admin.keyValid': '연결됨',
'admin.keyInvalid': '유효하지 않음',
+7
View File
@@ -91,6 +91,9 @@ const places: TranslationStrings = {
'places.loadingDetails': '장소 상세 정보 불러오는 중…',
'places.osmHint':
'OpenStreetMap 검색 사용 중 (사진, 영업 시간, 평점 없음). 전체 정보를 위해 설정에서 Google API 키를 추가하세요.',
'places.osmActive': 'OpenStreetMap을 사용 중입니다. Google API 키를 추가하면 평점과 영업시간이 표시됩니다.',
'places.osmActiveAmap': 'OpenStreetMap을 사용하고 있습니다. Amap(高德地图) API 키를 추가하면 평점과 영업시간을 볼 수 있습니다.',
'places.osmActiveAny': 'OpenStreetMap을 사용하고 있습니다. Google 또는 Amap(高德地图) API 키를 추가하면 평점과 영업시간을 볼 수 있습니다.',
'places.details.title': '장소 세부정보',
'places.details.empty': '결과를 선택하면 자세히 볼 수 있어요',
'places.details.loading': '세부정보를 불러오는 중...',
@@ -103,6 +106,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': '설명란을 먼저 비워 주세요',
'places.details.facts': '알아두면 좋아요',
'places.details.nothing': '이 장소에 대한 정보를 찾지 못했습니다.',
'places.details.noKeyTitle': '더 자세한 정보를 볼 수 있습니다',
'places.details.noKeyHint': 'Google API 키가 없으면 이 인스턴스는 무료 소스만 사용합니다. 평점, 영업시간, 사진을 보려면 TREK 관리자에게 키 추가를 요청하세요.',
'places.details.noKeyHintAmap': 'Amap(高德地图) API 키가 없으면 이 서버는 무료 출처만 사용할 수 있습니다. 평점과 영업시간을 위해 TREK 관리자에게 키 추가를 요청하세요.',
'places.details.noKeyHintAny': 'Google 또는 Amap(高德地图) API 키가 없으면 이 서버는 무료 출처만 사용할 수 있습니다. 평점과 영업시간을 위해 TREK 관리자에게 키 추가를 요청하세요.',
'places.details.aboutBrand': '체인 소개',
'places.details.aboutBrandNote': '이 지점이 아니라 체인에 대한 설명입니다.',
'places.details.fact.rating': '평점',
+12
View File
@@ -134,6 +134,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': 'Voor weergegevens. Gratis op openweathermap.org',
'admin.unsplashKey': 'Unsplash API-sleutel',
'admin.unsplashKeyHint': 'Voor het zoeken naar afbeeldingen. Gratis op unsplash.com/developers',
'admin.amapKey': 'Amap (高德地图) API-sleutel',
'admin.amapKeyHint':
'Voor het zoeken naar plaatsen in het Chinese vasteland, waar Google onbereikbaar is en OpenStreetMap weinig gegevens heeft. Vereist een sleutel van het type ‘Web 服务’ (webservice), geen JS API-sleutel. Verkrijgbaar op console.amap.com.',
'admin.placesProvider.title': 'Provider voor plaatszoeken',
'admin.placesProvider.subtitle':
'Welke dienst het zoeken naar plaatsen, de suggesties en de details verzorgt. Automatisch gebruikt Google als er een Google-sleutel is ingesteld, daarna Amap, daarna OpenStreetMap.',
'admin.placesProvider.auto': 'Automatisch',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap (高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': 'Voor de gekozen provider is geen API-sleutel ingesteld, dus het zoeken naar plaatsen valt terug op OpenStreetMap.',
'admin.placesProvider.saved': 'Provider voor plaatszoeken opgeslagen',
'admin.validateKey': 'Testen',
'admin.keyValid': 'Verbonden',
'admin.keyInvalid': 'Ongeldig',
+7
View File
@@ -92,6 +92,9 @@ const places: TranslationStrings = {
'places.loadingDetails': 'Plaatsgegevens laden…',
'places.osmHint':
"Zoeken via OpenStreetMap (geen foto's, openingstijden of beoordelingen). Voeg een Google API-sleutel toe in instellingen voor volledige details.",
'places.osmActive': 'OpenStreetMap wordt gebruikt. Een Google API-sleutel voegt beoordelingen en openingstijden toe.',
'places.osmActiveAmap': 'OpenStreetMap is actief. Een Amap (高德地图) API-sleutel voegt beoordelingen en openingstijden toe.',
'places.osmActiveAny': 'OpenStreetMap is actief. Een Google- of Amap (高德地图) API-sleutel voegt beoordelingen en openingstijden toe.',
'places.details.title': 'Plaatsdetails',
'places.details.empty': 'Kies een resultaat voor meer',
'places.details.loading': 'Details laden...',
@@ -104,6 +107,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': 'Maak eerst het beschrijvingsveld leeg',
'places.details.facts': 'Goed om te weten',
'places.details.nothing': 'Niets gevonden voor deze plaats.',
'places.details.noKeyTitle': 'Meer details beschikbaar',
'places.details.noKeyHint': 'Zonder Google API-sleutel gebruikt deze installatie alleen vrije bronnen. Vraag je TREK-beheerder er een toe te voegen voor beoordelingen, openingstijden en foto\'s.',
'places.details.noKeyHintAmap': 'Zonder Amap (高德地图) API-sleutel kan deze instantie alleen gratis bronnen gebruiken. Vraag de TREK-beheerder er een toe te voegen voor beoordelingen en openingstijden.',
'places.details.noKeyHintAny': 'Zonder Google- of Amap (高德地图) API-sleutel kan deze instantie alleen gratis bronnen gebruiken. Vraag de TREK-beheerder er een toe te voegen voor beoordelingen en openingstijden.',
'places.details.aboutBrand': 'Over de keten',
'places.details.aboutBrandNote': 'Beschrijft de keten, niet deze vestiging.',
'places.details.fact.rating': 'Beoordeling',
+12
View File
@@ -125,6 +125,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': 'Do danych pogodowych. Uzyskaj go bezpłatnie na openweathermap.org',
'admin.unsplashKey': 'Klucz API Unsplash',
'admin.unsplashKeyHint': 'Do wyszukiwania obrazów. Bezpłatnie na unsplash.com/developers',
'admin.amapKey': 'Klucz API Amap (高德地图)',
'admin.amapKeyHint':
'Do wyszukiwania miejsc w Chinach kontynentalnych, gdzie Google jest nieosiągalny, a OpenStreetMap ma niewiele danych. Wymaga klucza typu „Web 服务" (usługa sieciowa), a nie klucza JS API. Można go uzyskać na console.amap.com.',
'admin.placesProvider.title': 'Dostawca wyszukiwania miejsc',
'admin.placesProvider.subtitle':
'Która usługa obsługuje wyszukiwanie miejsc, podpowiedzi i szczegóły. Automatycznie używa Google, jeśli ustawiono klucz Google, następnie Amap, a potem OpenStreetMap.',
'admin.placesProvider.auto': 'Automatycznie',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap (高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': 'Wybrany dostawca nie ma ustawionego klucza API, więc wyszukiwanie miejsc wróci do OpenStreetMap.',
'admin.placesProvider.saved': 'Zapisano dostawcę wyszukiwania miejsc',
'admin.validateKey': 'Testuj',
'admin.keyValid': 'Połączono',
'admin.keyInvalid': 'Niepoprawny',
+7
View File
@@ -82,6 +82,9 @@ const places: TranslationStrings = {
'places.loadingDetails': 'Ładowanie szczegółów miejsca…',
'places.osmHint':
'Korzystając z OpenStreetMap (brak zdjęć, godzin otwarcia czy ocen). Dodaj klucz API Google w ustawieniach aby uzyskać pełne dane.',
'places.osmActive': 'Używany jest OpenStreetMap. Klucz Google API dodaje oceny i godziny otwarcia.',
'places.osmActiveAmap': 'Korzystasz z OpenStreetMap. Klucz API Amap (高德地图) dodaje oceny i godziny otwarcia.',
'places.osmActiveAny': 'Korzystasz z OpenStreetMap. Klucz API Google lub Amap (高德地图) dodaje oceny i godziny otwarcia.',
'places.details.title': 'Szczegóły miejsca',
'places.details.empty': 'Wybierz wynik, aby zobaczyć więcej',
'places.details.loading': 'Wczytywanie szczegółów...',
@@ -94,6 +97,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': 'Najpierw wyczyść pole opisu',
'places.details.facts': 'Warto wiedzieć',
'places.details.nothing': 'Nic nie znaleziono dla tego miejsca.',
'places.details.noKeyTitle': 'Dostępnych jest więcej szczegółów',
'places.details.noKeyHint': 'Bez klucza API Google ta instancja korzysta tylko ze źródeł otwartych. Poproś administratora TREK o dodanie klucza, aby uzyskać oceny, godziny otwarcia i zdjęcia.',
'places.details.noKeyHintAmap': 'Bez klucza API Amap (高德地图) ta instancja może korzystać tylko z darmowych źródeł. Poproś administratora TREK o dodanie klucza, aby uzyskać oceny i godziny otwarcia.',
'places.details.noKeyHintAny': 'Bez klucza API Google lub Amap (高德地图) ta instancja może korzystać tylko z darmowych źródeł. Poproś administratora TREK o dodanie klucza, aby uzyskać oceny i godziny otwarcia.',
'places.details.aboutBrand': 'O sieci',
'places.details.aboutBrandNote': 'Opisuje sieć, a nie ten lokal.',
'places.details.fact.rating': 'Ocena',
+12
View File
@@ -134,6 +134,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': 'Для данных о погоде. Бесплатно на openweathermap.org',
'admin.unsplashKey': 'Ключ API Unsplash',
'admin.unsplashKeyHint': 'Для поиска изображений. Бесплатно на unsplash.com/developers',
'admin.amapKey': 'API-ключ Amap (高德地图)',
'admin.amapKeyHint':
'Для поиска мест в континентальном Китае, где Google недоступен, а данных OpenStreetMap мало. Нужен ключ типа «Web 服务» (веб-сервис), а не ключ JS API. Получить можно на console.amap.com.',
'admin.placesProvider.title': 'Провайдер поиска мест',
'admin.placesProvider.subtitle':
'Какой сервис отвечает за поиск мест, подсказки и детали. «Автоматически» использует Google, если задан ключ Google, затем Amap, затем OpenStreetMap.',
'admin.placesProvider.auto': 'Автоматически',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap (高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': 'Для выбранного провайдера не задан API-ключ, поэтому поиск мест переключается на OpenStreetMap.',
'admin.placesProvider.saved': 'Провайдер поиска мест сохранён',
'admin.validateKey': 'Проверить',
'admin.keyValid': 'Подключено',
'admin.keyInvalid': 'Недействителен',
+7
View File
@@ -92,6 +92,9 @@ const places: TranslationStrings = {
'places.loadingDetails': 'Загрузка данных о месте…',
'places.osmHint':
'Поиск через OpenStreetMap (без фото, часов работы и рейтингов). Добавьте API-ключ Google в настройках для полной информации.',
'places.osmActive': 'Используется OpenStreetMap. Ключ Google API добавит рейтинги и часы работы.',
'places.osmActiveAmap': 'Используется OpenStreetMap. Ключ API Amap (高德地图) добавит оценки и часы работы.',
'places.osmActiveAny': 'Используется OpenStreetMap. Ключ API Google или Amap (高德地图) добавит оценки и часы работы.',
'places.details.title': 'Сведения о месте',
'places.details.empty': 'Выберите результат, чтобы узнать больше',
'places.details.loading': 'Загрузка сведений...',
@@ -104,6 +107,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': 'Сначала очистите поле описания',
'places.details.facts': 'Полезно знать',
'places.details.nothing': 'Для этого места ничего не найдено.',
'places.details.noKeyTitle': 'Доступно больше подробностей',
'places.details.noKeyHint': 'Без ключа Google API этот экземпляр использует только свободные источники. Попросите администратора TREK добавить ключ для оценок, часов работы и фотографий.',
'places.details.noKeyHintAmap': 'Без ключа API Amap (高德地图) этот сервер может использовать только бесплатные источники. Попросите администратора TREK добавить ключ — появятся оценки и часы работы.',
'places.details.noKeyHintAny': 'Без ключа API Google или Amap (高德地图) этот сервер может использовать только бесплатные источники. Попросите администратора TREK добавить ключ — появятся оценки и часы работы.',
'places.details.aboutBrand': 'О сети',
'places.details.aboutBrandNote': 'Описывает сеть, а не это заведение.',
'places.details.fact.rating': 'Рейтинг',
+12
View File
@@ -176,6 +176,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': "Hava durumu verileri için. openweathermap.org'da ücretsiz",
'admin.unsplashKey': 'Unsplash API Anahtarı',
'admin.unsplashKeyHint': "Görsel araması için. unsplash.com/developers'da ücretsiz",
'admin.amapKey': 'Amap (高德地图) API Anahtarı',
'admin.amapKeyHint':
'Google’ın erişilemediği ve OpenStreetMap verisinin çok az olduğu Çin anakarasında yer arama için. «Web 服务» (web servisi) türünde bir anahtar gerekir, JS API anahtarı değil. console.amap.com adresinden alınır.',
'admin.placesProvider.title': 'Yer arama sağlayıcısı',
'admin.placesProvider.subtitle':
'Yer aramasını, otomatik tamamlamayı ve ayrıntıları hangi servisin yanıtlayacağı. Otomatik, Google anahtarı varsa Google’ı, sonra Amap’i, sonra OpenStreetMap’i kullanır.',
'admin.placesProvider.auto': 'Otomatik',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap (高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': 'Seçilen sağlayıcı için API anahtarı ayarlanmamış, bu yüzden yer arama OpenStreetMap’e geri döner.',
'admin.placesProvider.saved': 'Yer arama sağlayıcısı kaydedildi',
'admin.validateKey': 'Test et',
'admin.keyValid': 'Bağlı',
'admin.keyInvalid': 'Geçersiz',
+7
View File
@@ -94,6 +94,9 @@ const places: TranslationStrings = {
'places.loadingDetails': 'Yer ayrıntıları yükleniyor…',
'places.osmHint':
'OpenStreetMap aramasını kullanma (fotoğraf, açılış saatleri veya derecelendirme yok). Tüm ayrıntılar için ayarlara bir Google API anahtarı ekleyin.',
'places.osmActive': 'OpenStreetMap kullanılıyor. Google API anahtarı puan ve çalışma saatleri ekler.',
'places.osmActiveAmap': 'OpenStreetMap kullanılıyor. Bir Amap (高德地图) API anahtarı puanlar ve çalışma saatleri ekler.',
'places.osmActiveAny': 'OpenStreetMap kullanılıyor. Bir Google veya Amap (高德地图) API anahtarı puanlar ve çalışma saatleri ekler.',
'places.details.title': 'Yer ayrıntıları',
'places.details.empty': 'Ayrıntılar için bir sonuç seç',
'places.details.loading': 'Ayrıntılar yükleniyor...',
@@ -106,6 +109,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': 'Önce açıklama alanını boşalt',
'places.details.facts': 'Bilmekte fayda var',
'places.details.nothing': 'Bu yer için bir şey bulunamadı.',
'places.details.noKeyTitle': 'Daha fazla ayrıntı mevcut',
'places.details.noKeyHint': 'Google API anahtarı olmadan bu örnek yalnızca özgür kaynakları kullanır. Puanlar, açılış saatleri ve fotoğraflar için TREK yöneticinizden bir anahtar eklemesini isteyin.',
'places.details.noKeyHintAmap': 'Amap (高德地图) API anahtarı olmadan bu sunucu yalnızca ücretsiz kaynakları kullanabilir. Puanlar ve çalışma saatleri için TREK yöneticisinden bir anahtar eklemesini isteyin.',
'places.details.noKeyHintAny': 'Google veya Amap (高德地图) API anahtarı olmadan bu sunucu yalnızca ücretsiz kaynakları kullanabilir. Puanlar ve çalışma saatleri için TREK yöneticisinden bir anahtar eklemesini isteyin.',
'places.details.aboutBrand': 'Zincir hakkında',
'places.details.aboutBrandNote': 'Bu şubeyi değil, zinciri anlatır.',
'places.details.fact.rating': 'Puan',
+12
View File
@@ -134,6 +134,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': 'Для даних про погоду. Безкоштовно на openweathermap.org',
'admin.unsplashKey': 'Ключ API Unsplash',
'admin.unsplashKeyHint': 'Для пошуку зображень. Безкоштовно на unsplash.com/developers',
'admin.amapKey': 'API-ключ Amap (高德地图)',
'admin.amapKeyHint':
'Для пошуку місць у континентальному Китаї, де Google недоступний, а даних OpenStreetMap обмаль. Потрібен ключ типу «Web 服务» (вебсервіс), а не ключ JS API. Отримати можна на console.amap.com.',
'admin.placesProvider.title': 'Постачальник пошуку місць',
'admin.placesProvider.subtitle':
'Яка служба відповідає за пошук місць, підказки та деталі. «Автоматично» використовує Google, якщо задано ключ Google, потім Amap, потім OpenStreetMap.',
'admin.placesProvider.auto': 'Автоматично',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': 'Amap (高德地图)',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': 'Для вибраного постачальника не задано API-ключ, тому пошук місць повертається до OpenStreetMap.',
'admin.placesProvider.saved': 'Постачальника пошуку місць збережено',
'admin.validateKey': 'Перевірити',
'admin.keyValid': 'Підключено',
'admin.keyInvalid': 'Недійсний',
+7
View File
@@ -92,6 +92,9 @@ const places: TranslationStrings = {
'places.loadingDetails': 'Завантаження даних про місце…',
'places.osmHint':
'Пошук через OpenStreetMap (без фото, годин роботи та рейтингів). Додайте API-ключ Google у налаштуваннях для повної інформації.',
'places.osmActive': 'Використовується OpenStreetMap. Ключ Google API додасть рейтинги та години роботи.',
'places.osmActiveAmap': 'Використовується OpenStreetMap. Ключ API Amap (高德地图) додасть оцінки й години роботи.',
'places.osmActiveAny': 'Використовується OpenStreetMap. Ключ API Google або Amap (高德地图) додасть оцінки й години роботи.',
'places.details.title': 'Відомості про місце',
'places.details.empty': 'Виберіть результат, щоб побачити більше',
'places.details.loading': 'Завантаження відомостей...',
@@ -104,6 +107,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': 'Спершу очистіть поле опису',
'places.details.facts': 'Корисно знати',
'places.details.nothing': 'Для цього місця нічого не знайдено.',
'places.details.noKeyTitle': 'Доступно більше деталей',
'places.details.noKeyHint': 'Без ключа Google API цей екземпляр використовує лише вільні джерела. Попросіть адміністратора TREK додати ключ, щоб отримати оцінки, години роботи та фото.',
'places.details.noKeyHintAmap': 'Без ключа API Amap (高德地图) цей сервер може використовувати лише безкоштовні джерела. Попросіть адміністратора TREK додати ключ — з’являться оцінки й години роботи.',
'places.details.noKeyHintAny': 'Без ключа API Google або Amap (高德地图) цей сервер може використовувати лише безкоштовні джерела. Попросіть адміністратора TREK додати ключ — з’являться оцінки й години роботи.',
'places.details.aboutBrand': 'Про мережу',
'places.details.aboutBrandNote': 'Описує мережу, а не цей заклад.',
'places.details.fact.rating': 'Рейтинг',
+12
View File
@@ -171,6 +171,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': '用於天氣資料。在 openweathermap.org 免費獲取',
'admin.unsplashKey': 'Unsplash API 金鑰',
'admin.unsplashKeyHint': '用於圖片搜尋。在 unsplash.com/developers 免費獲取',
'admin.amapKey': '高德地圖 API Key',
'admin.amapKeyHint':
'用於中國大陸境內的地點搜尋(Google 無法存取,OpenStreetMap 內容也很少)。需要「Web 服務」類型的 Key,而非 JS API Key。在 console.amap.com 申請。',
'admin.placesProvider.title': '地點搜尋來源',
'admin.placesProvider.subtitle':
'決定由哪個服務處理地點搜尋、輸入提示和詳情。自動:配了 Google Key 就用 Google,否則用高德,都沒有則用 OpenStreetMap。',
'admin.placesProvider.auto': '自動',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': '高德地圖',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': '所選來源尚未設定 API Key,地點搜尋會回退到 OpenStreetMap。',
'admin.placesProvider.saved': '地點搜尋來源已儲存',
'admin.validateKey': '測試',
'admin.keyValid': '已連線',
'admin.keyInvalid': '無效',
+7
View File
@@ -90,6 +90,9 @@ const places: TranslationStrings = {
'places.mapsSearchError': '地點搜尋失敗。',
'places.loadingDetails': '正在載入地點詳情…',
'places.osmHint': '使用 OpenStreetMap 搜尋(無照片、營業時間或評分)。在設定中新增 Google API 金鑰以獲取完整資訊。',
'places.osmActive': '正在使用 OpenStreetMap。加入 Google API 金鑰可取得評分與營業時間。',
'places.osmActiveAmap': '正在使用 OpenStreetMap。新增高德 API 金鑰可獲得評分和營業時間。',
'places.osmActiveAny': '正在使用 OpenStreetMap。新增 Google 或高德 API 金鑰可獲得評分和營業時間。',
'places.details.title': '地點詳細資料',
'places.details.empty': '選擇一個結果查看詳細資訊',
'places.details.loading': '正在載入詳細資料...',
@@ -102,6 +105,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': '請先清空描述欄位',
'places.details.facts': '值得一看',
'places.details.nothing': '找不到此地點的資訊。',
'places.details.noKeyTitle': '可取得更多詳細資訊',
'places.details.noKeyHint': '沒有 Google API 金鑰時,此執行個體僅使用免費來源。請聯絡 TREK 管理員新增金鑰,以取得評分、營業時間與照片。',
'places.details.noKeyHintAmap': '沒有高德 API 金鑰時,此實例僅使用免費來源。請聯絡 TREK 管理員新增金鑰,以取得評分和營業時間。',
'places.details.noKeyHintAny': '沒有 Google 或高德 API 金鑰時,此實例僅使用免費來源。請聯絡 TREK 管理員新增金鑰,以取得評分和營業時間。',
'places.details.aboutBrand': '關於該連鎖品牌',
'places.details.aboutBrandNote': '描述的是連鎖品牌,而非本分店。',
'places.details.fact.rating': '評分',
+12
View File
@@ -132,6 +132,18 @@ const admin: TranslationStrings = {
'admin.weatherKeyHint': '用于天气数据。在 openweathermap.org 免费获取',
'admin.unsplashKey': 'Unsplash API 密钥',
'admin.unsplashKeyHint': '用于图片搜索。在 unsplash.com/developers 免费获取',
'admin.amapKey': '高德地图 API Key',
'admin.amapKeyHint':
'用于中国大陆境内的地点搜索(Google 无法访问,OpenStreetMap 内容也很少)。需要「Web 服务」类型的 Key,不是 JS API Key。在 console.amap.com 申请。',
'admin.placesProvider.title': '地点搜索源',
'admin.placesProvider.subtitle':
'决定由哪个服务处理地点搜索、输入提示和详情。自动:配了 Google Key 就用 Google,否则用高德,都没有则用 OpenStreetMap。',
'admin.placesProvider.auto': '自动',
'admin.placesProvider.google': 'Google Places',
'admin.placesProvider.amap': '高德地图',
'admin.placesProvider.openstreetmap': 'OpenStreetMap',
'admin.placesProvider.missingKey': '所选源还没有配置 API Key,地点搜索会回退到 OpenStreetMap。',
'admin.placesProvider.saved': '地点搜索源已保存',
'admin.validateKey': '测试',
'admin.keyValid': '已连接',
'admin.keyInvalid': '无效',
+7
View File
@@ -90,6 +90,9 @@ const places: TranslationStrings = {
'places.mapsSearchError': '地点搜索失败。',
'places.loadingDetails': '正在加载地点详情…',
'places.osmHint': '使用 OpenStreetMap 搜索(无照片、营业时间或评分)。在设置中添加 Google API 密钥以获取完整信息。',
'places.osmActive': '正在使用 OpenStreetMap。添加 Google API 密钥可获得评分和营业时间。',
'places.osmActiveAmap': '正在使用 OpenStreetMap。添加高德 API 密钥可获得评分和营业时间。',
'places.osmActiveAny': '正在使用 OpenStreetMap。添加 Google 或高德 API 密钥可获得评分和营业时间。',
'places.details.title': '地点详情',
'places.details.empty': '选择一个结果查看详情',
'places.details.loading': '正在加载详情...',
@@ -102,6 +105,10 @@ const places: TranslationStrings = {
'places.details.adoptBlocked': '请先清空描述字段',
'places.details.facts': '值得一看',
'places.details.nothing': '未找到该地点的信息。',
'places.details.noKeyTitle': '可获取更多详情',
'places.details.noKeyHint': '没有 Google API 密钥时,此实例仅使用免费来源。请联系 TREK 管理员添加密钥,以获取评分、营业时间和照片。',
'places.details.noKeyHintAmap': '没有高德 API 密钥时,此实例仅使用免费来源。请联系 TREK 管理员添加密钥,以获取评分和营业时间。',
'places.details.noKeyHintAny': '没有 Google 或高德 API 密钥时,此实例仅使用免费来源。请联系 TREK 管理员添加密钥,以获取评分和营业时间。',
'places.details.aboutBrand': '关于该连锁品牌',
'places.details.aboutBrandNote': '描述的是连锁品牌,而非本门店。',
'places.details.fact.rating': '评分',
+4
View File
@@ -68,6 +68,10 @@ export * from './roadtrip/day-boundary.schema';
// has them ready if rich-text input ever ships.
export * from './sanitize/sanitize';
// WGS-84 ⇄ GCJ-02. Shared because the two boundaries that need it sit on
// opposite sides: the Amap provider on the server, the Leaflet CRS on the client.
export * from './geo/gcj02';
// i18n registry (language list + pure helpers — no locale data)
export * from './i18n/languages';