mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-21 14:36:31 +00:00
feat(tours): point a tour at its trip's packing list
A tour can now point at the packing list of its trip, as a whole or at one of its categories (say "Hiking gear" for a hike), and shows it in its detail. The new Packing list section reads the list live as the user may see it: the backpack tile with the item count on its corner and the category's own colour, how many are packed with a thin progress bar, the first items ticked off or not with their quantity, how many more there are, and a button that opens the trip's Lists tab. Who may change the tour links one, changes it or lets go through a dialog that lists the whole list and every category with its colour and item count, and writes only on its confirm. It is a reference, never a copy: the items stay in Packing, are ticked off and edited there, and each traveller sees in the tour only the items Packing shows them, so an item kept to oneself never shows through a tour. A category that is renamed, cleared or only holds items of others reads as missing, an empty one as empty, a link that could not be read says so with a retry, and while Lists are switched off the link stays, dimmed, and can still be let go. Removing the link, or the tour, leaves the list and every item as they are. Nothing suggests or changes an item by itself. On the server the link is a row of its own in the tours domain (tour_packing_links, migration 046110), one per tour and gone with it. GET, PUT and DELETE /api/trips/:tripId/tours/:placeId/packing-link read it with the trip and change it with place_edit; linking needs the Lists addon and, for a category, an item of it the user can see. The writes answer the tour with its link and tell the trip through tours:changed, so the offline client queues them as writes of the tour and replays them like one. A copied trip keeps its tours' links, a tour saved as new or taken over does not. The MCP tools get_tour_packing, link_tour_packing and unlink_tour_packing run over the same service and checks; the read also hands the tour's facts as context for suggesting what to pack, which only becomes an item through the packing tools. The empty category placeholder now lives in @trek/shared so both sides leave it out alike. All 27 locales carry the new strings, and the wiki describes the link and the tools.
This commit is contained in:
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'قائمة التجهيز',
|
||||
'tours.packing.none': 'لا توجد قائمة تجهيز مرتبطة',
|
||||
'tours.packing.link': 'ربط قائمة تجهيز',
|
||||
'tours.packing.change': 'تغيير',
|
||||
'tours.packing.whole': 'قائمة التجهيز كاملة',
|
||||
'tours.packing.packed': 'تم تجهيز {packed} من {count}',
|
||||
'tours.packing.packed.zero': 'تم تجهيز {packed} من {count}',
|
||||
'tours.packing.packed.one': 'تم تجهيز {packed} من {count}',
|
||||
'tours.packing.packed.two': 'تم تجهيز {packed} من {count}',
|
||||
'tours.packing.packed.few': 'تم تجهيز {packed} من {count}',
|
||||
'tours.packing.packed.many': 'تم تجهيز {packed} من {count}',
|
||||
'tours.packing.more': '+{count} أخرى',
|
||||
'tours.packing.more.zero': '+{count} أخرى',
|
||||
'tours.packing.more.one': '+{count} أخرى',
|
||||
'tours.packing.more.two': '+{count} أخرى',
|
||||
'tours.packing.more.few': '+{count} أخرى',
|
||||
'tours.packing.more.many': '+{count} أخرى',
|
||||
'tours.packing.items': '{count} غرض',
|
||||
'tours.packing.items.zero': '{count} غرض',
|
||||
'tours.packing.items.one': 'غرض واحد',
|
||||
'tours.packing.items.two': 'غرضان',
|
||||
'tours.packing.items.few': '{count} أغراض',
|
||||
'tours.packing.items.many': '{count} غرضًا',
|
||||
'tours.packing.allPacked': 'تم تجهيز الكل',
|
||||
'tours.packing.open': 'فتح قائمة التجهيز',
|
||||
'tours.packing.missing': 'لم تعد في «{name}» أغراض يمكنك رؤيتها.',
|
||||
'tours.packing.emptyList': 'قائمة التجهيز ما زالت فارغة.',
|
||||
'tours.packing.emptyCategory': 'لا توجد أغراض في «{name}» بعد.',
|
||||
'tours.packing.addonOff': 'قوائم التجهيز متوقفة، لذا لا يمكن عرض القائمة.',
|
||||
'tours.packing.loadFailed': 'تعذر تحميل ربط قائمة التجهيز.',
|
||||
'tours.packing.dialogSub': 'مجرد ربط. تبقى القائمة وأغراضها في مكانها.',
|
||||
'tours.packing.choose': 'الربط بـ',
|
||||
'tours.packing.confirm': 'ربط',
|
||||
'tours.packing.unlink': 'إزالة الربط',
|
||||
'tours.packing.unlinkHint': 'تبقى قائمة التجهيز وأغراضها كما هي',
|
||||
'tours.packing.linked': 'تم ربط قائمة التجهيز.',
|
||||
'tours.packing.unlinked': 'تمت إزالة الربط. تبقى قائمة التجهيز كما هي.',
|
||||
'tours.packing.failed': 'تعذر حفظ الربط.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -73,6 +74,7 @@ const locale = {
|
||||
...trip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...places,
|
||||
...inspector,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Baqaj siyahısı',
|
||||
'tours.packing.none': 'Bağlı baqaj siyahısı yoxdur',
|
||||
'tours.packing.link': 'Baqaj siyahısı bağla',
|
||||
'tours.packing.change': 'Dəyiş',
|
||||
'tours.packing.whole': 'Bütün baqaj siyahısı',
|
||||
'tours.packing.packed': '{count} əşyadan {packed} yığılıb',
|
||||
'tours.packing.packed.one': '{count} əşyadan {packed} yığılıb',
|
||||
'tours.packing.more': 'Daha {count}',
|
||||
'tours.packing.more.one': 'Daha {count}',
|
||||
'tours.packing.items': '{count} əşya',
|
||||
'tours.packing.items.one': '{count} əşya',
|
||||
'tours.packing.allPacked': 'Hamısı yığılıb',
|
||||
'tours.packing.open': 'Baqaj siyahısını aç',
|
||||
'tours.packing.missing': '“{name}” daxilində artıq görə biləcəyiniz əşya yoxdur.',
|
||||
'tours.packing.emptyList': 'Baqaj siyahısı hələ boşdur.',
|
||||
'tours.packing.emptyCategory': '“{name}” daxilində hələ əşya yoxdur.',
|
||||
'tours.packing.addonOff': 'Baqaj siyahıları söndürülüb, ona görə siyahı göstərilə bilmir.',
|
||||
'tours.packing.loadFailed': 'Baqaj siyahısı bağlantısı yüklənmədi.',
|
||||
'tours.packing.dialogSub': 'Sadəcə bağlantıdır. Siyahı və əşyaları olduğu yerdə qalır.',
|
||||
'tours.packing.choose': 'Hara bağlansın',
|
||||
'tours.packing.confirm': 'Bağla',
|
||||
'tours.packing.unlink': 'Bağlantını sil',
|
||||
'tours.packing.unlinkHint': 'Baqaj siyahısı və əşyaları olduğu kimi qalır',
|
||||
'tours.packing.linked': 'Baqaj siyahısı bağlandı.',
|
||||
'tours.packing.unlinked': 'Bağlantı silindi. Baqaj siyahısı olduğu kimi qalır.',
|
||||
'tours.packing.failed': 'Bağlantı saxlanılmadı.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Lista de mala',
|
||||
'tours.packing.none': 'Nenhuma lista de mala vinculada',
|
||||
'tours.packing.link': 'Vincular uma lista de mala',
|
||||
'tours.packing.change': 'Alterar',
|
||||
'tours.packing.whole': 'Lista de mala inteira',
|
||||
'tours.packing.packed': '{packed} de {count} na mala',
|
||||
'tours.packing.packed.one': '{packed} de {count} na mala',
|
||||
'tours.packing.more': '+{count} a mais',
|
||||
'tours.packing.more.one': '+{count} a mais',
|
||||
'tours.packing.items': '{count} objetos',
|
||||
'tours.packing.items.one': '{count} objeto',
|
||||
'tours.packing.allPacked': 'Tudo na mala',
|
||||
'tours.packing.open': 'Abrir a lista de mala',
|
||||
'tours.packing.missing': '“{name}” não tem mais objetos que você possa ver.',
|
||||
'tours.packing.emptyList': 'A lista de mala ainda está vazia.',
|
||||
'tours.packing.emptyCategory': '“{name}” ainda não tem objetos.',
|
||||
'tours.packing.addonOff': 'As listas de mala estão desativadas, então a lista não pode ser exibida.',
|
||||
'tours.packing.loadFailed': 'Não foi possível carregar o vínculo com a lista de mala.',
|
||||
'tours.packing.dialogSub': 'Apenas um vínculo. A lista e seus objetos ficam onde estão.',
|
||||
'tours.packing.choose': 'Vincular a',
|
||||
'tours.packing.confirm': 'Vincular',
|
||||
'tours.packing.unlink': 'Remover vínculo',
|
||||
'tours.packing.unlinkHint': 'A lista de mala e seus objetos ficam como estão',
|
||||
'tours.packing.linked': 'Lista de mala vinculada.',
|
||||
'tours.packing.unlinked': 'Vínculo removido. A lista de mala fica como está.',
|
||||
'tours.packing.failed': 'Não foi possível salvar o vínculo.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': "Llista d'equipatge",
|
||||
'tours.packing.none': "Cap llista d'equipatge vinculada",
|
||||
'tours.packing.link': "Vincula una llista d'equipatge",
|
||||
'tours.packing.change': 'Canvia',
|
||||
'tours.packing.whole': "Tota la llista d'equipatge",
|
||||
'tours.packing.packed': '{packed} de {count} empaquetats',
|
||||
'tours.packing.packed.one': '{packed} de {count} empaquetat',
|
||||
'tours.packing.more': '+{count} més',
|
||||
'tours.packing.more.one': '+{count} més',
|
||||
'tours.packing.items': '{count} articles',
|
||||
'tours.packing.items.one': '{count} article',
|
||||
'tours.packing.allPacked': 'Tot empaquetat',
|
||||
'tours.packing.open': "Obre la llista d'equipatge",
|
||||
'tours.packing.missing': '«{name}» ja no té articles que puguis veure.',
|
||||
'tours.packing.emptyList': "La llista d'equipatge encara és buida.",
|
||||
'tours.packing.emptyCategory': '«{name}» encara no té articles.',
|
||||
'tours.packing.addonOff': "Les llistes d'equipatge estan desactivades, així que la llista no es pot mostrar.",
|
||||
'tours.packing.loadFailed': "No s'ha pogut carregar el vincle amb la llista d'equipatge.",
|
||||
'tours.packing.dialogSub': 'Només un vincle. La llista i els seus articles es queden on són.',
|
||||
'tours.packing.choose': 'Vincula amb',
|
||||
'tours.packing.confirm': 'Vincula',
|
||||
'tours.packing.unlink': 'Treu el vincle',
|
||||
'tours.packing.unlinkHint': "La llista d'equipatge i els seus articles queden com són",
|
||||
'tours.packing.linked': "Llista d'equipatge vinculada.",
|
||||
'tours.packing.unlinked': "Vincle tret. La llista d'equipatge queda com és.",
|
||||
'tours.packing.failed': "No s'ha pogut desar el vincle.",
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Seznam věcí',
|
||||
'tours.packing.none': 'Žádný propojený seznam věcí',
|
||||
'tours.packing.link': 'Propojit seznam věcí',
|
||||
'tours.packing.change': 'Změnit',
|
||||
'tours.packing.whole': 'Celý seznam věcí',
|
||||
'tours.packing.packed': 'Zabaleno {packed} z {count}',
|
||||
'tours.packing.packed.one': 'Zabaleno {packed} z {count}',
|
||||
'tours.packing.packed.few': 'Zabaleno {packed} z {count}',
|
||||
'tours.packing.more': '+{count} dalších',
|
||||
'tours.packing.more.one': '+{count} další',
|
||||
'tours.packing.more.few': '+{count} další',
|
||||
'tours.packing.items': '{count} věcí',
|
||||
'tours.packing.items.one': '{count} věc',
|
||||
'tours.packing.items.few': '{count} věci',
|
||||
'tours.packing.allPacked': 'Vše zabaleno',
|
||||
'tours.packing.open': 'Otevřít seznam věcí',
|
||||
'tours.packing.missing': '„{name}“ už nemá žádné věci, které můžete vidět.',
|
||||
'tours.packing.emptyList': 'Seznam věcí je zatím prázdný.',
|
||||
'tours.packing.emptyCategory': '„{name}“ zatím nemá žádné věci.',
|
||||
'tours.packing.addonOff': 'Seznamy věcí jsou vypnuté, proto seznam nelze zobrazit.',
|
||||
'tours.packing.loadFailed': 'Propojení se seznamem věcí se nepodařilo načíst.',
|
||||
'tours.packing.dialogSub': 'Jen propojení. Seznam a jeho věci zůstávají, kde jsou.',
|
||||
'tours.packing.choose': 'Propojit s',
|
||||
'tours.packing.confirm': 'Propojit',
|
||||
'tours.packing.unlink': 'Zrušit propojení',
|
||||
'tours.packing.unlinkHint': 'Seznam věcí a jeho věci zůstanou beze změny',
|
||||
'tours.packing.linked': 'Seznam věcí propojen.',
|
||||
'tours.packing.unlinked': 'Propojení zrušeno. Seznam věcí zůstává beze změny.',
|
||||
'tours.packing.failed': 'Propojení se nepodařilo uložit.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Packliste',
|
||||
'tours.packing.none': 'Keine Packliste verknüpft',
|
||||
'tours.packing.link': 'Packliste verknüpfen',
|
||||
'tours.packing.change': 'Ändern',
|
||||
'tours.packing.whole': 'Ganze Packliste',
|
||||
'tours.packing.packed': '{packed} von {count} gepackt',
|
||||
'tours.packing.packed.one': '{packed} von {count} gepackt',
|
||||
'tours.packing.more': '+{count} weitere',
|
||||
'tours.packing.more.one': '+{count} weiteres',
|
||||
'tours.packing.items': '{count} Gegenstände',
|
||||
'tours.packing.items.one': '{count} Gegenstand',
|
||||
'tours.packing.allPacked': 'Alles gepackt',
|
||||
'tours.packing.open': 'Packliste öffnen',
|
||||
'tours.packing.missing': '„{name}“ hat keine Gegenstände mehr, die du sehen kannst.',
|
||||
'tours.packing.emptyList': 'Die Packliste ist noch leer.',
|
||||
'tours.packing.emptyCategory': '„{name}“ hat noch keine Gegenstände.',
|
||||
'tours.packing.addonOff': 'Packlisten sind ausgeschaltet, deshalb kann die Liste nicht angezeigt werden.',
|
||||
'tours.packing.loadFailed': 'Die Verknüpfung zur Packliste konnte nicht geladen werden.',
|
||||
'tours.packing.dialogSub': 'Nur eine Verknüpfung. Die Liste und ihre Gegenstände bleiben, wo sie sind.',
|
||||
'tours.packing.choose': 'Verknüpfen mit',
|
||||
'tours.packing.confirm': 'Verknüpfen',
|
||||
'tours.packing.unlink': 'Verknüpfung lösen',
|
||||
'tours.packing.unlinkHint': 'Die Packliste und ihre Gegenstände bleiben unverändert',
|
||||
'tours.packing.linked': 'Packliste verknüpft.',
|
||||
'tours.packing.unlinked': 'Verknüpfung gelöst. Die Packliste bleibt unverändert.',
|
||||
'tours.packing.failed': 'Die Verknüpfung konnte nicht gespeichert werden.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Packing list',
|
||||
'tours.packing.none': 'No packing list linked',
|
||||
'tours.packing.link': 'Link a packing list',
|
||||
'tours.packing.change': 'Change',
|
||||
'tours.packing.whole': 'Whole packing list',
|
||||
'tours.packing.packed': '{packed} of {count} packed',
|
||||
'tours.packing.packed.one': '{packed} of {count} packed',
|
||||
'tours.packing.more': '+{count} more',
|
||||
'tours.packing.more.one': '+{count} more',
|
||||
'tours.packing.items': '{count} items',
|
||||
'tours.packing.items.one': '{count} item',
|
||||
'tours.packing.allPacked': 'All packed',
|
||||
'tours.packing.open': 'Open packing list',
|
||||
'tours.packing.missing': '“{name}” has no items you can see any more.',
|
||||
'tours.packing.emptyList': 'The packing list is still empty.',
|
||||
'tours.packing.emptyCategory': '“{name}” has no items yet.',
|
||||
'tours.packing.addonOff': 'Packing lists are switched off, so the list cannot be shown.',
|
||||
'tours.packing.loadFailed': 'The packing link could not be loaded.',
|
||||
'tours.packing.dialogSub': 'Only a link. The list and its items stay where they are.',
|
||||
'tours.packing.choose': 'Link to',
|
||||
'tours.packing.confirm': 'Link',
|
||||
'tours.packing.unlink': 'Remove link',
|
||||
'tours.packing.unlinkHint': 'The packing list and its items stay as they are',
|
||||
'tours.packing.linked': 'Packing list linked.',
|
||||
'tours.packing.unlinked': 'Link removed. The packing list stays as it is.',
|
||||
'tours.packing.failed': 'The link could not be saved.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Lista de equipaje',
|
||||
'tours.packing.none': 'Ninguna lista de equipaje vinculada',
|
||||
'tours.packing.link': 'Vincular una lista de equipaje',
|
||||
'tours.packing.change': 'Cambiar',
|
||||
'tours.packing.whole': 'Toda la lista de equipaje',
|
||||
'tours.packing.packed': '{packed} de {count} empacados',
|
||||
'tours.packing.packed.one': '{packed} de {count} empacado',
|
||||
'tours.packing.more': '+{count} más',
|
||||
'tours.packing.more.one': '+{count} más',
|
||||
'tours.packing.items': '{count} artículos',
|
||||
'tours.packing.items.one': '{count} artículo',
|
||||
'tours.packing.allPacked': 'Todo empacado',
|
||||
'tours.packing.open': 'Abrir la lista de equipaje',
|
||||
'tours.packing.missing': '«{name}» ya no tiene artículos que puedas ver.',
|
||||
'tours.packing.emptyList': 'La lista de equipaje aún está vacía.',
|
||||
'tours.packing.emptyCategory': '«{name}» aún no tiene artículos.',
|
||||
'tours.packing.addonOff': 'Las listas de equipaje están desactivadas, así que la lista no se puede mostrar.',
|
||||
'tours.packing.loadFailed': 'No se pudo cargar el vínculo con la lista de equipaje.',
|
||||
'tours.packing.dialogSub': 'Solo un vínculo. La lista y sus artículos se quedan donde están.',
|
||||
'tours.packing.choose': 'Vincular con',
|
||||
'tours.packing.confirm': 'Vincular',
|
||||
'tours.packing.unlink': 'Quitar vínculo',
|
||||
'tours.packing.unlinkHint': 'La lista de equipaje y sus artículos quedan como están',
|
||||
'tours.packing.linked': 'Lista de equipaje vinculada.',
|
||||
'tours.packing.unlinked': 'Vínculo quitado. La lista de equipaje queda como está.',
|
||||
'tours.packing.failed': 'No se pudo guardar el vínculo.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -73,6 +74,7 @@ const locale = {
|
||||
...trip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...places,
|
||||
...inspector,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Pakkimisnimekiri',
|
||||
'tours.packing.none': 'Pakkimisnimekirja pole lingitud',
|
||||
'tours.packing.link': 'Lingi pakkimisnimekiri',
|
||||
'tours.packing.change': 'Muuda',
|
||||
'tours.packing.whole': 'Kogu pakkimisnimekiri',
|
||||
'tours.packing.packed': 'Pakitud {packed} / {count}',
|
||||
'tours.packing.packed.one': 'Pakitud {packed} / {count}',
|
||||
'tours.packing.more': 'Veel {count}',
|
||||
'tours.packing.more.one': 'Veel {count}',
|
||||
'tours.packing.items': '{count} asja',
|
||||
'tours.packing.items.one': '{count} asi',
|
||||
'tours.packing.allPacked': 'Kõik pakitud',
|
||||
'tours.packing.open': 'Ava pakkimisnimekiri',
|
||||
'tours.packing.missing': '„{name}“ juures pole enam ühtegi asja, mida sa näed.',
|
||||
'tours.packing.emptyList': 'Pakkimisnimekiri on veel tühi.',
|
||||
'tours.packing.emptyCategory': '„{name}“ juures pole veel ühtegi asja.',
|
||||
'tours.packing.addonOff': 'Pakkimisnimekirjad on välja lülitatud, seega nimekirja ei saa näidata.',
|
||||
'tours.packing.loadFailed': 'Pakkimisnimekirja linki ei õnnestunud laadida.',
|
||||
'tours.packing.dialogSub': 'Ainult link. Nimekiri ja selle asjad jäävad oma kohale.',
|
||||
'tours.packing.choose': 'Lingi sihtkoht',
|
||||
'tours.packing.confirm': 'Lingi',
|
||||
'tours.packing.unlink': 'Eemalda link',
|
||||
'tours.packing.unlinkHint': 'Pakkimisnimekiri ja selle asjad jäävad samaks',
|
||||
'tours.packing.linked': 'Pakkimisnimekiri on lingitud.',
|
||||
'tours.packing.unlinked': 'Link on eemaldatud. Pakkimisnimekiri jääb samaks.',
|
||||
'tours.packing.failed': 'Linki ei õnnestunud salvestada.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Liste de bagages',
|
||||
'tours.packing.none': 'Aucune liste de bagages liée',
|
||||
'tours.packing.link': 'Lier une liste de bagages',
|
||||
'tours.packing.change': 'Modifier',
|
||||
'tours.packing.whole': 'Toute la liste de bagages',
|
||||
'tours.packing.packed': '{packed} sur {count} emballés',
|
||||
'tours.packing.packed.one': '{packed} sur {count} emballé',
|
||||
'tours.packing.more': '+{count} autres',
|
||||
'tours.packing.more.one': '+{count} autre',
|
||||
'tours.packing.items': '{count} articles',
|
||||
'tours.packing.items.one': '{count} article',
|
||||
'tours.packing.allPacked': 'Tout est emballé',
|
||||
'tours.packing.open': 'Ouvrir la liste de bagages',
|
||||
'tours.packing.missing': '« {name} » n’a plus d’article visible pour vous.',
|
||||
'tours.packing.emptyList': 'La liste de bagages est encore vide.',
|
||||
'tours.packing.emptyCategory': '« {name} » n’a encore aucun article.',
|
||||
'tours.packing.addonOff': 'Les listes de bagages sont désactivées, la liste ne peut donc pas être affichée.',
|
||||
'tours.packing.loadFailed': 'Le lien vers la liste de bagages n’a pas pu être chargé.',
|
||||
'tours.packing.dialogSub': 'Un simple lien. La liste et ses articles restent où ils sont.',
|
||||
'tours.packing.choose': 'Lier à',
|
||||
'tours.packing.confirm': 'Lier',
|
||||
'tours.packing.unlink': 'Retirer le lien',
|
||||
'tours.packing.unlinkHint': 'La liste de bagages et ses articles restent tels quels',
|
||||
'tours.packing.linked': 'Liste de bagages liée.',
|
||||
'tours.packing.unlinked': 'Lien retiré. La liste de bagages reste telle quelle.',
|
||||
'tours.packing.failed': 'Le lien n’a pas pu être enregistré.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Λίστα αποσκευών',
|
||||
'tours.packing.none': 'Δεν έχει συνδεθεί λίστα αποσκευών',
|
||||
'tours.packing.link': 'Σύνδεση λίστας αποσκευών',
|
||||
'tours.packing.change': 'Αλλαγή',
|
||||
'tours.packing.whole': 'Όλη η λίστα αποσκευών',
|
||||
'tours.packing.packed': '{packed} από {count} στη βαλίτσα',
|
||||
'tours.packing.packed.one': '{packed} από {count} στη βαλίτσα',
|
||||
'tours.packing.more': '+{count} ακόμη',
|
||||
'tours.packing.more.one': '+{count} ακόμη',
|
||||
'tours.packing.items': '{count} αντικείμενα',
|
||||
'tours.packing.items.one': '{count} αντικείμενο',
|
||||
'tours.packing.allPacked': 'Όλα στη βαλίτσα',
|
||||
'tours.packing.open': 'Άνοιγμα λίστας αποσκευών',
|
||||
'tours.packing.missing': 'Το «{name}» δεν έχει πια αντικείμενα που μπορείτε να δείτε.',
|
||||
'tours.packing.emptyList': 'Η λίστα αποσκευών είναι ακόμη άδεια.',
|
||||
'tours.packing.emptyCategory': 'Το «{name}» δεν έχει ακόμη αντικείμενα.',
|
||||
'tours.packing.addonOff': 'Οι λίστες αποσκευών είναι απενεργοποιημένες, γι’ αυτό η λίστα δεν μπορεί να εμφανιστεί.',
|
||||
'tours.packing.loadFailed': 'Η σύνδεση με τη λίστα αποσκευών δεν φορτώθηκε.',
|
||||
'tours.packing.dialogSub': 'Μόνο μια σύνδεση. Η λίστα και τα αντικείμενά της μένουν εκεί που είναι.',
|
||||
'tours.packing.choose': 'Σύνδεση με',
|
||||
'tours.packing.confirm': 'Σύνδεση',
|
||||
'tours.packing.unlink': 'Αφαίρεση σύνδεσης',
|
||||
'tours.packing.unlinkHint': 'Η λίστα αποσκευών και τα αντικείμενά της μένουν ως έχουν',
|
||||
'tours.packing.linked': 'Η λίστα αποσκευών συνδέθηκε.',
|
||||
'tours.packing.unlinked': 'Η σύνδεση αφαιρέθηκε. Η λίστα αποσκευών μένει ως έχει.',
|
||||
'tours.packing.failed': 'Η σύνδεση δεν αποθηκεύτηκε.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Csomagolási lista',
|
||||
'tours.packing.none': 'Nincs csatolt csomagolási lista',
|
||||
'tours.packing.link': 'Csomagolási lista csatolása',
|
||||
'tours.packing.change': 'Módosítás',
|
||||
'tours.packing.whole': 'A teljes csomagolási lista',
|
||||
'tours.packing.packed': '{packed}/{count} becsomagolva',
|
||||
'tours.packing.packed.one': '{packed}/{count} becsomagolva',
|
||||
'tours.packing.more': 'További {count}',
|
||||
'tours.packing.more.one': 'További {count}',
|
||||
'tours.packing.items': '{count} tétel',
|
||||
'tours.packing.items.one': '{count} tétel',
|
||||
'tours.packing.allPacked': 'Minden becsomagolva',
|
||||
'tours.packing.open': 'Csomagolási lista megnyitása',
|
||||
'tours.packing.missing': 'A(z) „{name}” már nem tartalmaz látható tételt.',
|
||||
'tours.packing.emptyList': 'A csomagolási lista még üres.',
|
||||
'tours.packing.emptyCategory': 'A(z) „{name}” még nem tartalmaz tételt.',
|
||||
'tours.packing.addonOff': 'A csomagolási listák ki vannak kapcsolva, ezért a lista nem jeleníthető meg.',
|
||||
'tours.packing.loadFailed': 'A csomagolási lista csatolását nem sikerült betölteni.',
|
||||
'tours.packing.dialogSub': 'Csak egy csatolás. A lista és a tételei maradnak, ahol vannak.',
|
||||
'tours.packing.choose': 'Csatolás ehhez',
|
||||
'tours.packing.confirm': 'Csatolás',
|
||||
'tours.packing.unlink': 'Csatolás megszüntetése',
|
||||
'tours.packing.unlinkHint': 'A csomagolási lista és a tételei változatlanok maradnak',
|
||||
'tours.packing.linked': 'Csomagolási lista csatolva.',
|
||||
'tours.packing.unlinked': 'Csatolás megszüntetve. A csomagolási lista változatlan marad.',
|
||||
'tours.packing.failed': 'A csatolást nem sikerült menteni.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Daftar bawaan',
|
||||
'tours.packing.none': 'Belum ada daftar bawaan yang ditautkan',
|
||||
'tours.packing.link': 'Tautkan daftar bawaan',
|
||||
'tours.packing.change': 'Ubah',
|
||||
'tours.packing.whole': 'Seluruh daftar bawaan',
|
||||
'tours.packing.packed': '{packed} dari {count} sudah dikemas',
|
||||
'tours.packing.more': '+{count} lagi',
|
||||
'tours.packing.items': '{count} barang',
|
||||
'tours.packing.allPacked': 'Semua sudah dikemas',
|
||||
'tours.packing.open': 'Buka daftar bawaan',
|
||||
'tours.packing.missing': '“{name}” tidak lagi berisi barang yang bisa kamu lihat.',
|
||||
'tours.packing.emptyList': 'Daftar bawaan masih kosong.',
|
||||
'tours.packing.emptyCategory': '“{name}” belum berisi barang.',
|
||||
'tours.packing.addonOff': 'Daftar bawaan dinonaktifkan, jadi daftar ini tidak bisa ditampilkan.',
|
||||
'tours.packing.loadFailed': 'Tautan daftar bawaan tidak dapat dimuat.',
|
||||
'tours.packing.dialogSub': 'Hanya tautan. Daftar dan barangnya tetap di tempatnya.',
|
||||
'tours.packing.choose': 'Tautkan ke',
|
||||
'tours.packing.confirm': 'Tautkan',
|
||||
'tours.packing.unlink': 'Hapus tautan',
|
||||
'tours.packing.unlinkHint': 'Daftar bawaan dan barangnya tetap seperti semula',
|
||||
'tours.packing.linked': 'Daftar bawaan ditautkan.',
|
||||
'tours.packing.unlinked': 'Tautan dihapus. Daftar bawaan tetap seperti semula.',
|
||||
'tours.packing.failed': 'Tautan tidak dapat disimpan.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Lista valigia',
|
||||
'tours.packing.none': 'Nessuna lista valigia collegata',
|
||||
'tours.packing.link': 'Collega una lista valigia',
|
||||
'tours.packing.change': 'Cambia',
|
||||
'tours.packing.whole': 'Intera lista valigia',
|
||||
'tours.packing.packed': '{packed} di {count} in valigia',
|
||||
'tours.packing.packed.one': '{packed} di {count} in valigia',
|
||||
'tours.packing.more': '+{count} altri',
|
||||
'tours.packing.more.one': '+{count} altro',
|
||||
'tours.packing.items': '{count} oggetti',
|
||||
'tours.packing.items.one': '{count} oggetto',
|
||||
'tours.packing.allPacked': 'Tutto in valigia',
|
||||
'tours.packing.open': 'Apri la lista valigia',
|
||||
'tours.packing.missing': '“{name}” non ha più oggetti che puoi vedere.',
|
||||
'tours.packing.emptyList': 'La lista valigia è ancora vuota.',
|
||||
'tours.packing.emptyCategory': '“{name}” non ha ancora oggetti.',
|
||||
'tours.packing.addonOff': 'Le liste valigia sono disattivate, quindi la lista non può essere mostrata.',
|
||||
'tours.packing.loadFailed': 'Non è stato possibile caricare il collegamento alla lista valigia.',
|
||||
'tours.packing.dialogSub': 'Solo un collegamento. La lista e i suoi oggetti restano dove sono.',
|
||||
'tours.packing.choose': 'Collega a',
|
||||
'tours.packing.confirm': 'Collega',
|
||||
'tours.packing.unlink': 'Rimuovi collegamento',
|
||||
'tours.packing.unlinkHint': 'La lista valigia e i suoi oggetti restano come sono',
|
||||
'tours.packing.linked': 'Lista valigia collegata.',
|
||||
'tours.packing.unlinked': 'Collegamento rimosso. La lista valigia resta com’è.',
|
||||
'tours.packing.failed': 'Non è stato possibile salvare il collegamento.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': '持ち物リスト',
|
||||
'tours.packing.none': '持ち物リストはリンクされていません',
|
||||
'tours.packing.link': '持ち物リストをリンク',
|
||||
'tours.packing.change': '変更',
|
||||
'tours.packing.whole': '持ち物リスト全体',
|
||||
'tours.packing.packed': '{count} 件中 {packed} 件準備済み',
|
||||
'tours.packing.more': 'ほか {count} 件',
|
||||
'tours.packing.items': '{count} 件',
|
||||
'tours.packing.allPacked': 'すべて準備済み',
|
||||
'tours.packing.open': '持ち物リストを開く',
|
||||
'tours.packing.missing': '「{name}」には、表示できるアイテムがもうありません。',
|
||||
'tours.packing.emptyList': '持ち物リストはまだ空です。',
|
||||
'tours.packing.emptyCategory': '「{name}」にはまだアイテムがありません。',
|
||||
'tours.packing.addonOff': '持ち物リストがオフのため、リストを表示できません。',
|
||||
'tours.packing.loadFailed': '持ち物リストのリンクを読み込めませんでした。',
|
||||
'tours.packing.dialogSub': 'リンクするだけです。リストとアイテムはそのまま残ります。',
|
||||
'tours.packing.choose': 'リンク先',
|
||||
'tours.packing.confirm': 'リンク',
|
||||
'tours.packing.unlink': 'リンクを解除',
|
||||
'tours.packing.unlinkHint': '持ち物リストとアイテムはそのまま残ります',
|
||||
'tours.packing.linked': '持ち物リストをリンクしました。',
|
||||
'tours.packing.unlinked': 'リンクを解除しました。持ち物リストはそのままです。',
|
||||
'tours.packing.failed': 'リンクを保存できませんでした。',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': '짐 목록',
|
||||
'tours.packing.none': '연결된 짐 목록 없음',
|
||||
'tours.packing.link': '짐 목록 연결',
|
||||
'tours.packing.change': '변경',
|
||||
'tours.packing.whole': '짐 목록 전체',
|
||||
'tours.packing.packed': '{count}개 중 {packed}개 챙김',
|
||||
'tours.packing.more': '{count}개 더',
|
||||
'tours.packing.items': '{count}개',
|
||||
'tours.packing.allPacked': '모두 챙김',
|
||||
'tours.packing.open': '짐 목록 열기',
|
||||
'tours.packing.missing': '“{name}”에 더 이상 볼 수 있는 물품이 없습니다.',
|
||||
'tours.packing.emptyList': '짐 목록이 아직 비어 있습니다.',
|
||||
'tours.packing.emptyCategory': '“{name}”에 아직 물품이 없습니다.',
|
||||
'tours.packing.addonOff': '짐 목록이 꺼져 있어 목록을 표시할 수 없습니다.',
|
||||
'tours.packing.loadFailed': '짐 목록 연결을 불러오지 못했습니다.',
|
||||
'tours.packing.dialogSub': '연결만 합니다. 목록과 물품은 그대로 남습니다.',
|
||||
'tours.packing.choose': '연결 대상',
|
||||
'tours.packing.confirm': '연결',
|
||||
'tours.packing.unlink': '연결 해제',
|
||||
'tours.packing.unlinkHint': '짐 목록과 물품은 그대로 유지됩니다',
|
||||
'tours.packing.linked': '짐 목록을 연결했습니다.',
|
||||
'tours.packing.unlinked': '연결을 해제했습니다. 짐 목록은 그대로입니다.',
|
||||
'tours.packing.failed': '연결을 저장하지 못했습니다.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Inpaklijst',
|
||||
'tours.packing.none': 'Geen inpaklijst gekoppeld',
|
||||
'tours.packing.link': 'Inpaklijst koppelen',
|
||||
'tours.packing.change': 'Wijzigen',
|
||||
'tours.packing.whole': 'Hele inpaklijst',
|
||||
'tours.packing.packed': '{packed} van {count} ingepakt',
|
||||
'tours.packing.packed.one': '{packed} van {count} ingepakt',
|
||||
'tours.packing.more': '+{count} meer',
|
||||
'tours.packing.more.one': '+{count} meer',
|
||||
'tours.packing.items': '{count} artikelen',
|
||||
'tours.packing.items.one': '{count} artikel',
|
||||
'tours.packing.allPacked': 'Alles ingepakt',
|
||||
'tours.packing.open': 'Inpaklijst openen',
|
||||
'tours.packing.missing': '‘{name}’ heeft geen spullen meer die je kunt zien.',
|
||||
'tours.packing.emptyList': 'De inpaklijst is nog leeg.',
|
||||
'tours.packing.emptyCategory': '‘{name}’ heeft nog geen spullen.',
|
||||
'tours.packing.addonOff': 'Inpaklijsten zijn uitgeschakeld, dus de lijst kan niet worden getoond.',
|
||||
'tours.packing.loadFailed': 'De koppeling met de inpaklijst kon niet worden geladen.',
|
||||
'tours.packing.dialogSub': 'Alleen een koppeling. De lijst en de spullen erin blijven waar ze zijn.',
|
||||
'tours.packing.choose': 'Koppelen aan',
|
||||
'tours.packing.confirm': 'Koppelen',
|
||||
'tours.packing.unlink': 'Koppeling verwijderen',
|
||||
'tours.packing.unlinkHint': 'De inpaklijst en de spullen erin blijven zoals ze zijn',
|
||||
'tours.packing.linked': 'Inpaklijst gekoppeld.',
|
||||
'tours.packing.unlinked': 'Koppeling verwijderd. De inpaklijst blijft zoals hij is.',
|
||||
'tours.packing.failed': 'De koppeling kon niet worden opgeslagen.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Lista pakowania',
|
||||
'tours.packing.none': 'Brak połączonej listy pakowania',
|
||||
'tours.packing.link': 'Połącz listę pakowania',
|
||||
'tours.packing.change': 'Zmień',
|
||||
'tours.packing.whole': 'Cała lista pakowania',
|
||||
'tours.packing.packed': 'Spakowano {packed} z {count}',
|
||||
'tours.packing.packed.one': 'Spakowano {packed} z {count}',
|
||||
'tours.packing.packed.few': 'Spakowano {packed} z {count}',
|
||||
'tours.packing.packed.many': 'Spakowano {packed} z {count}',
|
||||
'tours.packing.more': '+{count} więcej',
|
||||
'tours.packing.more.one': '+{count} więcej',
|
||||
'tours.packing.more.few': '+{count} więcej',
|
||||
'tours.packing.more.many': '+{count} więcej',
|
||||
'tours.packing.items': '{count} rzeczy',
|
||||
'tours.packing.items.one': '{count} rzecz',
|
||||
'tours.packing.items.few': '{count} rzeczy',
|
||||
'tours.packing.items.many': '{count} rzeczy',
|
||||
'tours.packing.allPacked': 'Wszystko spakowane',
|
||||
'tours.packing.open': 'Otwórz listę pakowania',
|
||||
'tours.packing.missing': '„{name}” nie ma już rzeczy, które możesz zobaczyć.',
|
||||
'tours.packing.emptyList': 'Lista pakowania jest jeszcze pusta.',
|
||||
'tours.packing.emptyCategory': '„{name}” nie ma jeszcze rzeczy.',
|
||||
'tours.packing.addonOff': 'Listy pakowania są wyłączone, więc nie można pokazać listy.',
|
||||
'tours.packing.loadFailed': 'Nie udało się wczytać połączenia z listą pakowania.',
|
||||
'tours.packing.dialogSub': 'Tylko połączenie. Lista i jej rzeczy zostają tam, gdzie są.',
|
||||
'tours.packing.choose': 'Połącz z',
|
||||
'tours.packing.confirm': 'Połącz',
|
||||
'tours.packing.unlink': 'Usuń połączenie',
|
||||
'tours.packing.unlinkHint': 'Lista pakowania i jej rzeczy zostają bez zmian',
|
||||
'tours.packing.linked': 'Lista pakowania połączona.',
|
||||
'tours.packing.unlinked': 'Połączenie usunięte. Lista pakowania zostaje bez zmian.',
|
||||
'tours.packing.failed': 'Nie udało się zapisać połączenia.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Список вещей',
|
||||
'tours.packing.none': 'Список вещей не привязан',
|
||||
'tours.packing.link': 'Привязать список вещей',
|
||||
'tours.packing.change': 'Изменить',
|
||||
'tours.packing.whole': 'Весь список вещей',
|
||||
'tours.packing.packed': 'Упаковано {packed} из {count}',
|
||||
'tours.packing.packed.one': 'Упаковано {packed} из {count}',
|
||||
'tours.packing.packed.few': 'Упаковано {packed} из {count}',
|
||||
'tours.packing.packed.many': 'Упаковано {packed} из {count}',
|
||||
'tours.packing.more': 'Ещё {count}',
|
||||
'tours.packing.more.one': 'Ещё {count}',
|
||||
'tours.packing.more.few': 'Ещё {count}',
|
||||
'tours.packing.more.many': 'Ещё {count}',
|
||||
'tours.packing.items': 'Вещей: {count}',
|
||||
'tours.packing.items.one': '{count} вещь',
|
||||
'tours.packing.items.few': '{count} вещи',
|
||||
'tours.packing.items.many': '{count} вещей',
|
||||
'tours.packing.allPacked': 'Всё упаковано',
|
||||
'tours.packing.open': 'Открыть список вещей',
|
||||
'tours.packing.missing': 'В «{name}» больше нет вещей, которые вы можете видеть.',
|
||||
'tours.packing.emptyList': 'Список вещей пока пуст.',
|
||||
'tours.packing.emptyCategory': 'В «{name}» пока нет вещей.',
|
||||
'tours.packing.addonOff': 'Списки вещей отключены, поэтому список нельзя показать.',
|
||||
'tours.packing.loadFailed': 'Не удалось загрузить привязку к списку вещей.',
|
||||
'tours.packing.dialogSub': 'Только привязка. Список и его вещи остаются на месте.',
|
||||
'tours.packing.choose': 'Привязать к',
|
||||
'tours.packing.confirm': 'Привязать',
|
||||
'tours.packing.unlink': 'Отвязать',
|
||||
'tours.packing.unlinkHint': 'Список вещей и его вещи останутся без изменений',
|
||||
'tours.packing.linked': 'Список вещей привязан.',
|
||||
'tours.packing.unlinked': 'Привязка снята. Список вещей остаётся без изменений.',
|
||||
'tours.packing.failed': 'Не удалось сохранить привязку.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -73,6 +74,7 @@ const locale = {
|
||||
...trip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...places,
|
||||
...inspector,
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Zoznam vecí',
|
||||
'tours.packing.none': 'Žiadny prepojený zoznam vecí',
|
||||
'tours.packing.link': 'Prepojiť zoznam vecí',
|
||||
'tours.packing.change': 'Zmeniť',
|
||||
'tours.packing.whole': 'Celý zoznam vecí',
|
||||
'tours.packing.packed': 'Zbalené {packed} z {count}',
|
||||
'tours.packing.packed.one': 'Zbalené {packed} z {count}',
|
||||
'tours.packing.packed.few': 'Zbalené {packed} z {count}',
|
||||
'tours.packing.more': '+{count} ďalších',
|
||||
'tours.packing.more.one': '+{count} ďalšia',
|
||||
'tours.packing.more.few': '+{count} ďalšie',
|
||||
'tours.packing.items': '{count} vecí',
|
||||
'tours.packing.items.one': '{count} vec',
|
||||
'tours.packing.items.few': '{count} veci',
|
||||
'tours.packing.allPacked': 'Všetko zbalené',
|
||||
'tours.packing.open': 'Otvoriť zoznam vecí',
|
||||
'tours.packing.missing': '„{name}“ už nemá žiadne veci, ktoré môžete vidieť.',
|
||||
'tours.packing.emptyList': 'Zoznam vecí je zatiaľ prázdny.',
|
||||
'tours.packing.emptyCategory': '„{name}“ zatiaľ nemá žiadne veci.',
|
||||
'tours.packing.addonOff': 'Zoznamy vecí sú vypnuté, preto zoznam nemožno zobraziť.',
|
||||
'tours.packing.loadFailed': 'Prepojenie so zoznamom vecí sa nepodarilo načítať.',
|
||||
'tours.packing.dialogSub': 'Len prepojenie. Zoznam a jeho veci zostávajú, kde sú.',
|
||||
'tours.packing.choose': 'Prepojiť s',
|
||||
'tours.packing.confirm': 'Prepojiť',
|
||||
'tours.packing.unlink': 'Zrušiť prepojenie',
|
||||
'tours.packing.unlinkHint': 'Zoznam vecí a jeho veci zostanú bez zmeny',
|
||||
'tours.packing.linked': 'Zoznam vecí je prepojený.',
|
||||
'tours.packing.unlinked': 'Prepojenie zrušené. Zoznam vecí zostáva bez zmeny.',
|
||||
'tours.packing.failed': 'Prepojenie sa nepodarilo uložiť.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Packlista',
|
||||
'tours.packing.none': 'Ingen packlista kopplad',
|
||||
'tours.packing.link': 'Koppla en packlista',
|
||||
'tours.packing.change': 'Ändra',
|
||||
'tours.packing.whole': 'Hela packlistan',
|
||||
'tours.packing.packed': '{packed} av {count} packade',
|
||||
'tours.packing.packed.one': '{packed} av {count} packad',
|
||||
'tours.packing.more': '+{count} till',
|
||||
'tours.packing.more.one': '+{count} till',
|
||||
'tours.packing.items': '{count} saker',
|
||||
'tours.packing.items.one': '{count} sak',
|
||||
'tours.packing.allPacked': 'Allt packat',
|
||||
'tours.packing.open': 'Öppna packlistan',
|
||||
'tours.packing.missing': '”{name}” har inga saker kvar som du kan se.',
|
||||
'tours.packing.emptyList': 'Packlistan är fortfarande tom.',
|
||||
'tours.packing.emptyCategory': '”{name}” har inga saker än.',
|
||||
'tours.packing.addonOff': 'Packlistor är avstängda, så listan kan inte visas.',
|
||||
'tours.packing.loadFailed': 'Kopplingen till packlistan kunde inte läsas in.',
|
||||
'tours.packing.dialogSub': 'Bara en koppling. Listan och sakerna i den stannar där de är.',
|
||||
'tours.packing.choose': 'Koppla till',
|
||||
'tours.packing.confirm': 'Koppla',
|
||||
'tours.packing.unlink': 'Ta bort koppling',
|
||||
'tours.packing.unlinkHint': 'Packlistan och sakerna i den förblir som de är',
|
||||
'tours.packing.linked': 'Packlista kopplad.',
|
||||
'tours.packing.unlinked': 'Kopplingen är borttagen. Packlistan förblir som den är.',
|
||||
'tours.packing.failed': 'Kopplingen kunde inte sparas.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -73,6 +74,7 @@ const locale = {
|
||||
...trip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...places,
|
||||
...inspector,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'รายการจัดกระเป๋า',
|
||||
'tours.packing.none': 'ยังไม่ได้ลิงก์รายการจัดกระเป๋า',
|
||||
'tours.packing.link': 'ลิงก์รายการจัดกระเป๋า',
|
||||
'tours.packing.change': 'เปลี่ยน',
|
||||
'tours.packing.whole': 'รายการจัดกระเป๋าทั้งหมด',
|
||||
'tours.packing.packed': 'จัดแล้ว {packed} จาก {count}',
|
||||
'tours.packing.more': 'อีก {count} รายการ',
|
||||
'tours.packing.items': '{count} รายการ',
|
||||
'tours.packing.allPacked': 'จัดครบแล้ว',
|
||||
'tours.packing.open': 'เปิดรายการจัดกระเป๋า',
|
||||
'tours.packing.missing': '“{name}” ไม่มีของที่คุณมองเห็นได้อีกแล้ว',
|
||||
'tours.packing.emptyList': 'รายการจัดกระเป๋ายังว่างอยู่',
|
||||
'tours.packing.emptyCategory': '“{name}” ยังไม่มีของ',
|
||||
'tours.packing.addonOff': 'รายการจัดกระเป๋าถูกปิดอยู่ จึงแสดงรายการไม่ได้',
|
||||
'tours.packing.loadFailed': 'โหลดลิงก์รายการจัดกระเป๋าไม่ได้',
|
||||
'tours.packing.dialogSub': 'เป็นเพียงลิงก์ รายการและของในรายการยังอยู่ที่เดิม',
|
||||
'tours.packing.choose': 'ลิงก์ไปยัง',
|
||||
'tours.packing.confirm': 'ลิงก์',
|
||||
'tours.packing.unlink': 'เลิกลิงก์',
|
||||
'tours.packing.unlinkHint': 'รายการจัดกระเป๋าและของในรายการยังคงเหมือนเดิม',
|
||||
'tours.packing.linked': 'ลิงก์รายการจัดกระเป๋าแล้ว',
|
||||
'tours.packing.unlinked': 'เลิกลิงก์แล้ว รายการจัดกระเป๋ายังคงเหมือนเดิม',
|
||||
'tours.packing.failed': 'บันทึกลิงก์ไม่ได้',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -14,9 +14,9 @@ type DomainModules = Record<string, { default: TranslationStrings }>;
|
||||
const toursModules = import.meta.glob<{ default: TranslationStrings }>('./*/tours.ts', { eager: true });
|
||||
|
||||
// The tours strings live in more than one file per locale, so that none of
|
||||
// them grows past the size limit: `tours.ts` holds the planner, and
|
||||
// `tourCollection.ts` the tours kept in a collection. Each file is held to
|
||||
// its own count.
|
||||
// them grows past the size limit: `tours.ts` holds the planner,
|
||||
// `tourCollection.ts` the tours kept in a collection and `tourPacking.ts` the
|
||||
// packing list a tour points at. Each file is held to its own count.
|
||||
const TOUR_DOMAINS: { file: string; generalKeyCount: number; modules: DomainModules }[] = [
|
||||
{
|
||||
file: 'tours',
|
||||
@@ -28,6 +28,11 @@ const TOUR_DOMAINS: { file: string; generalKeyCount: number; modules: DomainModu
|
||||
generalKeyCount: 41,
|
||||
modules: import.meta.glob<{ default: TranslationStrings }>('./*/tourCollection.ts', { eager: true }),
|
||||
},
|
||||
{
|
||||
file: 'tourPacking',
|
||||
generalKeyCount: 23,
|
||||
modules: import.meta.glob<{ default: TranslationStrings }>('./*/tourPacking.ts', { eager: true }),
|
||||
},
|
||||
];
|
||||
const aggregates = import.meta.glob<{ default: TranslationStrings }>('./*/index.ts', { eager: true });
|
||||
const tokens = (value: string) => [...value.matchAll(/\{[^{}]+\}/g)].map((match) => match[0]).sort();
|
||||
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Paket listesi',
|
||||
'tours.packing.none': 'Bağlı paket listesi yok',
|
||||
'tours.packing.link': 'Paket listesi bağla',
|
||||
'tours.packing.change': 'Değiştir',
|
||||
'tours.packing.whole': 'Tüm paket listesi',
|
||||
'tours.packing.packed': '{count} eşyadan {packed} tanesi paketlendi',
|
||||
'tours.packing.packed.one': '{count} eşyadan {packed} tanesi paketlendi',
|
||||
'tours.packing.more': '{count} tane daha',
|
||||
'tours.packing.more.one': '{count} tane daha',
|
||||
'tours.packing.items': '{count} eşya',
|
||||
'tours.packing.items.one': '{count} eşya',
|
||||
'tours.packing.allPacked': 'Hepsi paketlendi',
|
||||
'tours.packing.open': 'Paket listesini aç',
|
||||
'tours.packing.missing': '“{name}” içinde artık görebileceğiniz eşya yok.',
|
||||
'tours.packing.emptyList': 'Paket listesi henüz boş.',
|
||||
'tours.packing.emptyCategory': '“{name}” içinde henüz eşya yok.',
|
||||
'tours.packing.addonOff': 'Paket listeleri kapalı, bu yüzden liste gösterilemiyor.',
|
||||
'tours.packing.loadFailed': 'Paket listesi bağlantısı yüklenemedi.',
|
||||
'tours.packing.dialogSub': 'Yalnızca bir bağlantı. Liste ve eşyaları olduğu yerde kalır.',
|
||||
'tours.packing.choose': 'Bağlanacak yer',
|
||||
'tours.packing.confirm': 'Bağla',
|
||||
'tours.packing.unlink': 'Bağlantıyı kaldır',
|
||||
'tours.packing.unlinkHint': 'Paket listesi ve eşyaları olduğu gibi kalır',
|
||||
'tours.packing.linked': 'Paket listesi bağlandı.',
|
||||
'tours.packing.unlinked': 'Bağlantı kaldırıldı. Paket listesi olduğu gibi kalır.',
|
||||
'tours.packing.failed': 'Bağlantı kaydedilemedi.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Список речей',
|
||||
'tours.packing.none': 'Список речей не прив’язано',
|
||||
'tours.packing.link': 'Прив’язати список речей',
|
||||
'tours.packing.change': 'Змінити',
|
||||
'tours.packing.whole': 'Увесь список речей',
|
||||
'tours.packing.packed': 'Спаковано {packed} з {count}',
|
||||
'tours.packing.packed.one': 'Спаковано {packed} з {count}',
|
||||
'tours.packing.packed.few': 'Спаковано {packed} з {count}',
|
||||
'tours.packing.packed.many': 'Спаковано {packed} з {count}',
|
||||
'tours.packing.more': 'Ще {count}',
|
||||
'tours.packing.more.one': 'Ще {count}',
|
||||
'tours.packing.more.few': 'Ще {count}',
|
||||
'tours.packing.more.many': 'Ще {count}',
|
||||
'tours.packing.items': 'Речей: {count}',
|
||||
'tours.packing.items.one': '{count} річ',
|
||||
'tours.packing.items.few': '{count} речі',
|
||||
'tours.packing.items.many': '{count} речей',
|
||||
'tours.packing.allPacked': 'Усе спаковано',
|
||||
'tours.packing.open': 'Відкрити список речей',
|
||||
'tours.packing.missing': 'У «{name}» більше немає речей, які ви можете бачити.',
|
||||
'tours.packing.emptyList': 'Список речей поки порожній.',
|
||||
'tours.packing.emptyCategory': 'У «{name}» поки немає речей.',
|
||||
'tours.packing.addonOff': 'Списки речей вимкнено, тому список неможливо показати.',
|
||||
'tours.packing.loadFailed': 'Не вдалося завантажити прив’язку до списку речей.',
|
||||
'tours.packing.dialogSub': 'Лише прив’язка. Список і його речі залишаються на місці.',
|
||||
'tours.packing.choose': 'Прив’язати до',
|
||||
'tours.packing.confirm': 'Прив’язати',
|
||||
'tours.packing.unlink': 'Відв’язати',
|
||||
'tours.packing.unlinkHint': 'Список речей і його речі залишаться без змін',
|
||||
'tours.packing.linked': 'Список речей прив’язано.',
|
||||
'tours.packing.unlinked': 'Прив’язку знято. Список речей залишається без змін.',
|
||||
'tours.packing.failed': 'Не вдалося зберегти прив’язку.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': 'Danh sách đóng gói',
|
||||
'tours.packing.none': 'Chưa liên kết danh sách đóng gói',
|
||||
'tours.packing.link': 'Liên kết danh sách đóng gói',
|
||||
'tours.packing.change': 'Thay đổi',
|
||||
'tours.packing.whole': 'Toàn bộ danh sách đóng gói',
|
||||
'tours.packing.packed': 'Đã đóng gói {packed}/{count}',
|
||||
'tours.packing.more': '+{count} món nữa',
|
||||
'tours.packing.items': '{count} món',
|
||||
'tours.packing.allPacked': 'Đã đóng gói hết',
|
||||
'tours.packing.open': 'Mở danh sách đóng gói',
|
||||
'tours.packing.missing': '“{name}” không còn món nào bạn có thể xem.',
|
||||
'tours.packing.emptyList': 'Danh sách đóng gói vẫn còn trống.',
|
||||
'tours.packing.emptyCategory': '“{name}” chưa có món nào.',
|
||||
'tours.packing.addonOff': 'Danh sách đóng gói đang tắt nên không thể hiển thị danh sách.',
|
||||
'tours.packing.loadFailed': 'Không tải được liên kết danh sách đóng gói.',
|
||||
'tours.packing.dialogSub': 'Chỉ là liên kết. Danh sách và các món trong đó vẫn ở nguyên chỗ.',
|
||||
'tours.packing.choose': 'Liên kết với',
|
||||
'tours.packing.confirm': 'Liên kết',
|
||||
'tours.packing.unlink': 'Gỡ liên kết',
|
||||
'tours.packing.unlinkHint': 'Danh sách đóng gói và các món trong đó giữ nguyên',
|
||||
'tours.packing.linked': 'Đã liên kết danh sách đóng gói.',
|
||||
'tours.packing.unlinked': 'Đã gỡ liên kết. Danh sách đóng gói vẫn giữ nguyên.',
|
||||
'tours.packing.failed': 'Không lưu được liên kết.',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': '行李清單',
|
||||
'tours.packing.none': '未連結行李清單',
|
||||
'tours.packing.link': '連結行李清單',
|
||||
'tours.packing.change': '變更',
|
||||
'tours.packing.whole': '整份行李清單',
|
||||
'tours.packing.packed': '已打包 {packed}/{count}',
|
||||
'tours.packing.more': '還有 {count} 項',
|
||||
'tours.packing.items': '{count} 項',
|
||||
'tours.packing.allPacked': '全部已打包',
|
||||
'tours.packing.open': '開啟行李清單',
|
||||
'tours.packing.missing': '「{name}」中已沒有你能看到的物品。',
|
||||
'tours.packing.emptyList': '行李清單還是空的。',
|
||||
'tours.packing.emptyCategory': '「{name}」中還沒有物品。',
|
||||
'tours.packing.addonOff': '行李清單已關閉,因此無法顯示該清單。',
|
||||
'tours.packing.loadFailed': '無法載入行李清單連結。',
|
||||
'tours.packing.dialogSub': '只是連結。清單及其物品保持不變。',
|
||||
'tours.packing.choose': '連結到',
|
||||
'tours.packing.confirm': '連結',
|
||||
'tours.packing.unlink': '取消連結',
|
||||
'tours.packing.unlinkHint': '行李清單及其物品保持不變',
|
||||
'tours.packing.linked': '已連結行李清單。',
|
||||
'tours.packing.unlinked': '已取消連結。行李清單保持不變。',
|
||||
'tours.packing.failed': '無法儲存連結。',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -47,6 +47,7 @@ import storage from './storage';
|
||||
import system_notice from './system_notice';
|
||||
import todo from './todo';
|
||||
import tourCollection from './tourCollection';
|
||||
import tourPacking from './tourPacking';
|
||||
import tours from './tours';
|
||||
import transport from './transport';
|
||||
import trip from './trip';
|
||||
@@ -63,6 +64,7 @@ const locale = {
|
||||
...roadtrip,
|
||||
...tours,
|
||||
...tourCollection,
|
||||
...tourPacking,
|
||||
...wanderer,
|
||||
...settings,
|
||||
...admin,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { TranslationStrings } from '../types';
|
||||
|
||||
const tourPacking: TranslationStrings = {
|
||||
'tours.packing.label': '行李清单',
|
||||
'tours.packing.none': '未关联行李清单',
|
||||
'tours.packing.link': '关联行李清单',
|
||||
'tours.packing.change': '更改',
|
||||
'tours.packing.whole': '整个行李清单',
|
||||
'tours.packing.packed': '已打包 {packed}/{count}',
|
||||
'tours.packing.more': '还有 {count} 项',
|
||||
'tours.packing.items': '{count} 项',
|
||||
'tours.packing.allPacked': '全部已打包',
|
||||
'tours.packing.open': '打开行李清单',
|
||||
'tours.packing.missing': '“{name}”中已没有你能看到的物品。',
|
||||
'tours.packing.emptyList': '行李清单还是空的。',
|
||||
'tours.packing.emptyCategory': '“{name}”中还没有物品。',
|
||||
'tours.packing.addonOff': '行李清单已关闭,因此无法显示该清单。',
|
||||
'tours.packing.loadFailed': '无法加载行李清单关联。',
|
||||
'tours.packing.dialogSub': '只是关联。清单及其物品保持不变。',
|
||||
'tours.packing.choose': '关联到',
|
||||
'tours.packing.confirm': '关联',
|
||||
'tours.packing.unlink': '取消关联',
|
||||
'tours.packing.unlinkHint': '行李清单及其物品保持不变',
|
||||
'tours.packing.linked': '已关联行李清单。',
|
||||
'tours.packing.unlinked': '已取消关联。行李清单保持不变。',
|
||||
'tours.packing.failed': '无法保存关联。',
|
||||
};
|
||||
export default tourPacking;
|
||||
@@ -34,6 +34,7 @@ export * from './atlas/atlas.schema';
|
||||
export * from './vacay/vacay.schema';
|
||||
export * from './packing/packing.schema';
|
||||
export * from './packing/packed-count';
|
||||
export * from './packing/packing-placeholder';
|
||||
export * from './todo/todo.schema';
|
||||
export * from './budget/budget.schema';
|
||||
export * from './budget/receipt-scan.schema';
|
||||
@@ -64,6 +65,8 @@ export * from './tours/tour-activity-stats.schema';
|
||||
export * from './tours/tour-activity-stats';
|
||||
export * from './tours/tour-library.schema';
|
||||
export * from './tours/collection-tour.schema';
|
||||
export * from './tours/tour-packing-link.schema';
|
||||
export * from './tours/tour-packing-link';
|
||||
export * from './tours/tour-poi-search.schema';
|
||||
export * from './tours/tour-trail-grade.schema';
|
||||
export * from './tours/tour-walk.schema';
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* The name the first item of a new, still empty packing category carries.
|
||||
* The server refuses an item without a name, so an empty category lives on an
|
||||
* item of this name; no list shows it as an item or counts it.
|
||||
*/
|
||||
export const PACKING_PLACEHOLDER_NAME = '...';
|
||||
@@ -0,0 +1,30 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/**
|
||||
* P2D-XD-01: a tour points at the packing list of its trip, as a whole or at
|
||||
* one of its categories (a sub-list such as "Hiking gear"). The link only
|
||||
* names what it points at; the items stay in Packing, which owns their
|
||||
* content, editing and lifecycle, and decides who sees which of them.
|
||||
*/
|
||||
|
||||
/** A category of the trip's packing list, exactly as its items carry it. */
|
||||
export const tourPackingCategorySchema = z.string().min(1).max(200);
|
||||
|
||||
/** What a tour points at: null for the whole packing list, otherwise one of its categories. */
|
||||
export const tourPackingLinkRequestSchema = z.object({
|
||||
category: tourPackingCategorySchema.nullable(),
|
||||
});
|
||||
export type TourPackingLinkRequest = z.infer<typeof tourPackingLinkRequestSchema>;
|
||||
|
||||
/** The link a tour's detail carries: what it points at and when it was made. */
|
||||
export const tourPackingLinkSchema = z.object({
|
||||
category: z.string().nullable(),
|
||||
linked_at: z.string(),
|
||||
});
|
||||
export type TourPackingLink = z.infer<typeof tourPackingLinkSchema>;
|
||||
|
||||
/** GET .../tours/:placeId/packing-link: what the tour points at, null while it points at nothing. */
|
||||
export const tourPackingLinkResponseSchema = z.object({
|
||||
packing_link: tourPackingLinkSchema.nullable(),
|
||||
});
|
||||
export type TourPackingLinkResponse = z.infer<typeof tourPackingLinkResponseSchema>;
|
||||
@@ -0,0 +1,76 @@
|
||||
import { PACKING_PLACEHOLDER_NAME } from '../packing/packing-placeholder';
|
||||
import { linkedPackingItems, packingCategoriesOf } from './tour-packing-link';
|
||||
import {
|
||||
tourPackingLinkRequestSchema,
|
||||
tourPackingLinkResponseSchema,
|
||||
tourPackingLinkSchema,
|
||||
} from './tour-packing-link.schema';
|
||||
import { tourCreateResponseSchema } from './tours.schema';
|
||||
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
const items = [
|
||||
{ id: 1, name: 'Boots', category: 'Hiking gear', checked: 1 },
|
||||
{ id: 2, name: 'Rain jacket', category: 'Hiking gear', checked: 0 },
|
||||
{ id: 3, name: 'Passport', category: 'Documents', checked: 0 },
|
||||
{ id: 4, name: PACKING_PLACEHOLDER_NAME, category: 'Snacks', checked: 0 },
|
||||
{ id: 5, name: 'Old charger', category: null, checked: true },
|
||||
];
|
||||
|
||||
describe('tour packing link contract (P2D-XD-01)', () => {
|
||||
it('TPL-SCHEMA-001: points at the whole list with null and at a category by its exact name', () => {
|
||||
expect(tourPackingLinkRequestSchema.parse({ category: null })).toEqual({ category: null });
|
||||
expect(tourPackingLinkRequestSchema.parse({ category: ' Hiking gear ' })).toEqual({ category: ' Hiking gear ' });
|
||||
expect(tourPackingLinkRequestSchema.safeParse({ category: '' }).success).toBe(false);
|
||||
expect(tourPackingLinkRequestSchema.safeParse({ category: 'x'.repeat(201) }).success).toBe(false);
|
||||
expect(tourPackingLinkRequestSchema.safeParse({}).success).toBe(false);
|
||||
});
|
||||
|
||||
it('TPL-SCHEMA-002: a link write answers the tour with its link, null without one; other answers carry none', () => {
|
||||
const link = { category: 'Hiking gear', linked_at: '2026-10-20 09:00:00' };
|
||||
expect(tourPackingLinkSchema.parse(link)).toEqual(link);
|
||||
expect(tourPackingLinkSchema.safeParse({ category: null }).success).toBe(false);
|
||||
const field = tourCreateResponseSchema.shape.packing_link;
|
||||
expect(field.parse(link)).toEqual(link);
|
||||
expect(field.parse(null)).toBeNull();
|
||||
expect(field.parse(undefined)).toBeUndefined();
|
||||
expect(tourPackingLinkResponseSchema.parse({ packing_link: null })).toEqual({ packing_link: null });
|
||||
expect(tourPackingLinkResponseSchema.safeParse({}).success).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('linkedPackingItems (P2D-XD-01)', () => {
|
||||
it('TPL-ITEMS-001: the whole list shows every item but an empty category placeholder', () => {
|
||||
const linked = linkedPackingItems({ category: null }, items);
|
||||
expect(linked.state).toBe('ready');
|
||||
expect(linked.items.map((item) => item.id)).toEqual([1, 2, 3, 5]);
|
||||
expect(linked.packed).toBe(2);
|
||||
});
|
||||
|
||||
it('TPL-ITEMS-002: a category shows its own items in their order and counts the ticked ones', () => {
|
||||
const linked = linkedPackingItems({ category: 'Hiking gear' }, items);
|
||||
expect(linked).toEqual({ state: 'ready', items: [items[0], items[1]], packed: 1 });
|
||||
});
|
||||
|
||||
it('TPL-ITEMS-003: an empty list and a category that holds only its placeholder read as empty', () => {
|
||||
expect(linkedPackingItems({ category: null }, []).state).toBe('empty');
|
||||
expect(linkedPackingItems({ category: 'Snacks' }, items)).toEqual({ state: 'empty', items: [], packed: 0 });
|
||||
});
|
||||
|
||||
it('TPL-ITEMS-004: a category without an item the viewer can see reads as missing, never as empty', () => {
|
||||
expect(linkedPackingItems({ category: 'Climbing' }, items)).toEqual({ state: 'missing', items: [], packed: 0 });
|
||||
// The name is compared as it is stored: another spelling is another category.
|
||||
expect(linkedPackingItems({ category: 'hiking gear' }, items).state).toBe('missing');
|
||||
});
|
||||
});
|
||||
|
||||
describe('packingCategoriesOf (P2D-XD-01)', () => {
|
||||
it('TPL-CATS-001: names each category once, in the order the list first shows it, with its items counted', () => {
|
||||
expect(packingCategoriesOf(items)).toEqual([
|
||||
{ name: 'Hiking gear', count: 2 },
|
||||
{ name: 'Documents', count: 1 },
|
||||
{ name: 'Snacks', count: 0 },
|
||||
]);
|
||||
expect(packingCategoriesOf([])).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,64 @@
|
||||
import { PACKING_PLACEHOLDER_NAME } from '../packing/packing-placeholder';
|
||||
import type { TourPackingLink } from './tour-packing-link.schema';
|
||||
|
||||
/** What a packing item has to say for a tour's link to show it. */
|
||||
export interface LinkablePackingItem {
|
||||
name: string;
|
||||
category?: string | null;
|
||||
checked?: number | boolean | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* How a tour's packing link reads against the items its viewer can see:
|
||||
* `ready` shows at least one item; `empty` points at something that is there
|
||||
* but holds no item yet (an empty packing list, a category just made);
|
||||
* `missing` names a category without one item the viewer can see, because it
|
||||
* was renamed or cleared, or its items are kept to other travellers.
|
||||
*/
|
||||
export type TourPackingLinkState = 'ready' | 'empty' | 'missing';
|
||||
|
||||
export interface LinkedPackingItems<T> {
|
||||
state: TourPackingLinkState;
|
||||
/** The items of the list or category, in the order Packing lists them. */
|
||||
items: T[];
|
||||
/** How many of them are ticked off. */
|
||||
packed: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* The items a link shows, read from the packing items the viewer can see, so
|
||||
* what one traveller keeps to themselves never shows through a tour. Nothing
|
||||
* here writes: the list, its categories and its items stay Packing's.
|
||||
*/
|
||||
export function linkedPackingItems<T extends LinkablePackingItem>(
|
||||
link: Pick<TourPackingLink, 'category'>,
|
||||
visible: readonly T[],
|
||||
): LinkedPackingItems<T> {
|
||||
const inScope = link.category === null ? visible : visible.filter((item) => item.category === link.category);
|
||||
const items = inScope.filter((item) => item.name !== PACKING_PLACEHOLDER_NAME);
|
||||
let state: TourPackingLinkState = 'ready';
|
||||
if (items.length === 0) state = link.category === null || inScope.length > 0 ? 'empty' : 'missing';
|
||||
return { state, items, packed: items.filter((item) => Boolean(item.checked)).length };
|
||||
}
|
||||
|
||||
/** A category a tour can point at: its name and how many items it holds. */
|
||||
export interface PackingCategoryChoice {
|
||||
name: string;
|
||||
count: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* The named categories of a packing list in the order the list first shows
|
||||
* them, each with its items counted (an empty category's placeholder is no
|
||||
* item). Items without a category sit in no category a tour can point at;
|
||||
* the whole list takes them in.
|
||||
*/
|
||||
export function packingCategoriesOf(visible: readonly LinkablePackingItem[]): PackingCategoryChoice[] {
|
||||
const counts = new Map<string, number>();
|
||||
for (const item of visible) {
|
||||
if (!item.category) continue;
|
||||
const counted = item.name === PACKING_PLACEHOLDER_NAME ? 0 : 1;
|
||||
counts.set(item.category, (counts.get(item.category) ?? 0) + counted);
|
||||
}
|
||||
return [...counts].map(([name, count]) => ({ name, count }));
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
import { runPaceSecondsPerKmSchema } from './run-pace';
|
||||
import { skiDisciplineSchema, skiTechniqueSchema } from './ski.schema';
|
||||
import { tourActivityRefSchema, tourActivitySchema } from './tour-activity.schema';
|
||||
import { tourPackingLinkSchema } from './tour-packing-link.schema';
|
||||
import { tourPoiCategorySchema } from './tour-poi-category';
|
||||
import { tourOriginSchema, tourProvenanceSchema } from './tour-provenance.schema';
|
||||
import { maxTourMinutesFor, TOUR_DAY_MINUTES, tourStageCountOf, tourStageIssues } from './tour-stages';
|
||||
@@ -728,6 +729,12 @@ export const tourCreateResponseSchema = z.object({
|
||||
obstacle_check: tourObstacleCheckSchema.optional().catch(undefined),
|
||||
/** ACT-01: the recorded tracks assigned to the tour; absent only in a detail cached before TREK sent them. */
|
||||
activities: z.array(tourActivitySchema).optional(),
|
||||
/**
|
||||
* P2D-XD-01: the packing list or category the tour points at, null for none.
|
||||
* The packing link writes answer with it; an answer without it says nothing
|
||||
* about the link, so a cache keeps the one it had.
|
||||
*/
|
||||
packing_link: tourPackingLinkSchema.nullable().optional(),
|
||||
});
|
||||
export type TourCreateResponse = z.infer<typeof tourCreateResponseSchema>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user