4418594af0
The controller new/edit modal hardcoded both its outputs and its inputs, so an
operator could neither add a generic event-driven relay nor a free-standing input
(e.g. a second radar at the exit). This unifies both into symmetric, first-class
lists. Behaviour for existing booths is unchanged (back-compat, no DB migration).
Outputs — one event→action relays[] list:
- A relay is "when EVENT X happens, do its action": entry/exit/both pulse a
barrier; a new `radarAlert` event drives a non-barrier alert lamp (blink while
its trigger input is active, SOLID once the camera confirms a car).
- Dropped the separate config.buttonLight block — the lamp is just a relays[] row
with direction:"radarAlert" (triggerInput + blink cadence). `alertRelaysOf()`
replaces `buttonLightOf()`; ButtonLightController keeps its proven 3-state
machine (serialized UDP, fail-OFF, hot-reload), now keyed per controllerId:relay
so several alert lamps on one controller run independently. Every barrier
resolver skips radarAlert rows (no auto-open; barrier-not-a-door intact).
Inputs — one first-class config.inputs[] list (the twin of relays[]):
- Each row is { input, role, relay?, kind?, activeLow?, cooldownSec? } with a
"+ Add input" button. role ∈ button | presence | alertTrigger; button/presence
name the relay they serve. An exit radar is just another presence row.
- Keystone `inputsOf(row)`: returns config.inputs[] or SYNTHESIZES it from the
legacy relays[].button/presenceInput/... fields, so relayForButton /
relayForPresence resolve identically from either shape — zero-downtime, no
migration. entry-flow.ts is unchanged (resolves through the same functions).
- Fixed a latent bug this exposed: the alert lamp's camera lock was hardcoded to
the ENTRY camera. Added relays[].lockLane ("entry"|"exit", default entry); the
lamp now locks on its own lane's camera, so an exit radar's lamp tracks the exit
camera. button-light tracks both #entryBusy/#exitBusy.
- Driver: extracted activeLowFrom(config) — merges inputs[] activeLow, legacy
relays[].presenceActiveLow, and the inputActiveLow escape hatch.
UI: the relay dropdown gained a "Radar alert" option (reveals trigger/lock/blink
inputs); InputEditor is rewritten to a generic list (role select folds loop/radar);
i18n sq+en kept at type-parity.
Tests: new device-resolve.test.ts (inputs[] resolution + legacy fallback identical
+ exit-radar resolves to the exit relay); button-light gains a two-independent-
alert-relays case and an exit-lamp lockLane case; access-dingtian gains
activeLowFrom cases. Full workspace build/lint/test green (i18n parity included).
Wiki + memory updated (button-light-indicator, entry-double-press, dingtian-relay).
Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
921 lines
38 KiB
TypeScript
921 lines
38 KiB
TypeScript
// Albanian (sq) — the DEFAULT and fallback language. Customer/operator-facing copy.
|
||
// Keys are dot-namespaced by area (common, nav, booth, …). When adding a string,
|
||
// add it here first (the fallback), then mirror the key in en.ts.
|
||
// See wiki/concepts/i18n.md.
|
||
|
||
export const sq = {
|
||
common: {
|
||
loading: "Duke u ngarkuar…",
|
||
logout: "Dil",
|
||
cancel: "Anulo",
|
||
close: "Mbyll",
|
||
save: "Ruaj",
|
||
none: "—",
|
||
themeDark: "errët",
|
||
themeLight: "çelët",
|
||
theme: "Tema",
|
||
today: "Sot",
|
||
yesterday: "Dje",
|
||
// Month names (index 0 = January) — kept in the catalog because the appliance's
|
||
// browser ICU may lack Albanian locale data (Intl falls back to English).
|
||
months: [
|
||
"Janar",
|
||
"Shkurt",
|
||
"Mars",
|
||
"Prill",
|
||
"Maj",
|
||
"Qershor",
|
||
"Korrik",
|
||
"Gusht",
|
||
"Shtator",
|
||
"Tetor",
|
||
"Nëntor",
|
||
"Dhjetor",
|
||
],
|
||
},
|
||
auth: {
|
||
title: "Sistemi i Parkimit",
|
||
username: "Përdoruesi",
|
||
password: "Fjalëkalimi",
|
||
signIn: "Hyr",
|
||
signingIn: "Duke hyrë…",
|
||
},
|
||
update: {
|
||
available: "Përditësim i disponueshëm",
|
||
prompt: "Versioni {{version}} është i disponueshëm. Ta instaloj tani dhe ta rinis?",
|
||
},
|
||
nav: {
|
||
booth: "Kabina",
|
||
shift: "Turni",
|
||
setup: "Konfigurimi",
|
||
devices: "Pajisjet",
|
||
tariff: "Tarifa",
|
||
tariffLab: "Lab Tarife",
|
||
subscriptions: "Abonimet",
|
||
plans: "Planet",
|
||
site: "Park",
|
||
users: "Përdoruesit",
|
||
roles: "Rolet",
|
||
shifts: "Turnet",
|
||
reports: "Raportet",
|
||
recycleBin: "Koshi",
|
||
logs: "Loget",
|
||
profile: "Profili",
|
||
},
|
||
profile: {
|
||
title: "Profili im",
|
||
accountSection: "Llogaria",
|
||
fullName: "Emri i plotë",
|
||
fullNamePh: "Emri dhe mbiemri",
|
||
email: "Email",
|
||
emailPh: "ti@shembull.com",
|
||
username: "Përdoruesi",
|
||
role: "Roli",
|
||
saveProfile: "Ruaj profilin",
|
||
profileSaved: "Profili u ruajt.",
|
||
passwordSection: "Ndrysho fjalëkalimin",
|
||
currentPassword: "Fjalëkalimi aktual",
|
||
newPassword: "Fjalëkalimi i ri",
|
||
confirmPassword: "Konfirmo fjalëkalimin",
|
||
changePassword: "Ndrysho fjalëkalimin",
|
||
passwordChanged: "Fjalëkalimi u ndryshua.",
|
||
passwordsDontMatch: "Fjalëkalimet nuk përputhen.",
|
||
passwordTooShort: "Fjalëkalimi duhet të jetë të paktën {{min}} karaktere.",
|
||
},
|
||
status: {
|
||
live: "LIVE",
|
||
connecting: "DUKE U LIDHUR",
|
||
offline: "JASHTË LINJE",
|
||
},
|
||
devices: {
|
||
footerTitle: "Pajisjet",
|
||
none: "Asnjë pajisje e konfiguruar.",
|
||
catAccess: "Rele",
|
||
catReader: "Lexuesi",
|
||
catCamera: "Kamera",
|
||
catPrinter: "Printer",
|
||
catVision: "ANPR",
|
||
// Role/direction suffixes for the chip label (e.g. "Lexuesi hyrje").
|
||
role: {
|
||
entry: "hyrje",
|
||
exit: "dalje",
|
||
both: "hyrje/dalje",
|
||
mixed: "hyrje/dalje",
|
||
lane: "në korsi",
|
||
booth: "në kabinë",
|
||
},
|
||
state: {
|
||
ready: "gati",
|
||
degraded: "i dëmtuar",
|
||
offline: "jashtë linje",
|
||
},
|
||
allOk: "të gjitha gati",
|
||
issuesCount: "{{count}} me probleme",
|
||
issuesTitle: "Problemet e pajisjeve",
|
||
clickForIssues: "Kliko për detajet",
|
||
checkedAt: "kontrolluar {{time}}",
|
||
},
|
||
booth: {
|
||
processTicket: "Proceso biletën",
|
||
scanPlaceholder: "Skano ose shkruaj numrin e biletës…",
|
||
laneEntry: "Hyrje",
|
||
laneExit: "Dalje",
|
||
open: "Hap",
|
||
occupancy: "Prania",
|
||
occUnavailable: "zënia e padisponueshme",
|
||
inside: "brenda",
|
||
of: "nga",
|
||
uncapped: "pa kufi",
|
||
free: "Vende të lira",
|
||
lotFull: "● parkimi plot",
|
||
liveFeed: "Aktiviteti live",
|
||
events: "Evente",
|
||
noEventsYet: "Asnjë event ende — hyrjet dhe daljet do të shfaqen këtu.",
|
||
activeSessions: "Sesionet aktive",
|
||
insideCount: "brenda",
|
||
noActiveSessions: "Asnjë sesion aktiv.",
|
||
noMatch: "Asnjë rezultat për filtrin.",
|
||
badgeOverstay: "tej afatit",
|
||
badgeOverstayTitle:
|
||
"Sesion i paguar. Klienti nuk doli brënda afatit kohor. Ka filluar një periudhë e re tarifimi.",
|
||
plateTitle: "Targa e njohur nga ANPR",
|
||
// filtra
|
||
filterSearchSessions: "Kërko biletë / abonent / targë…",
|
||
filterSearchFeed: "Kërko event / identitet / targë…",
|
||
filterAll: "Të gjitha",
|
||
fStatusUnpaid: "Papaguar",
|
||
fStatusPaid: "Paguar",
|
||
fStatusExiting: "Duke dalë",
|
||
fStatusOverstay: "Tej afatit",
|
||
fKindTransient: "Kalimtarë",
|
||
fKindSubscription: "Abonentë",
|
||
fDirEntry: "Hyrje",
|
||
fDirExit: "Dalje",
|
||
fSrcBooth: "Kabinë",
|
||
fSrcReader: "Lexues",
|
||
fEvtEntry: "Hyrje",
|
||
fEvtExit: "Dalje",
|
||
fEvtPay: "Pagesë",
|
||
fEvtVoid: "Anulim",
|
||
fEvtAnomaly: "Anomali",
|
||
openPayExit: "Hap pagesën / daljen",
|
||
openBarrier: "Hap barrierën",
|
||
openBarrierTitle: "Hap barrierën manualisht",
|
||
barrierOpened: "barriera u hap",
|
||
openManually: "hape me dorë",
|
||
// session row badges
|
||
badgeExiting: "duke dalë",
|
||
badgePaid: "paguar",
|
||
badgeUnpaid: "papaguar",
|
||
badgeSubscription: "abonim",
|
||
// event types (live feed labels)
|
||
evtEntry: "HYRJE",
|
||
evtExit: "DALJE",
|
||
evtPay: "PAGESË",
|
||
evtVoid: "ANULIM",
|
||
evtOpenCmd: "HAP→",
|
||
evtOpenObserved: "HAP✓",
|
||
evtShiftOpen: "TURN+",
|
||
evtShiftZ: "TURN Z",
|
||
evtCashMovement: "ARKË",
|
||
evtCashIn: "ARKËTIM",
|
||
evtCashOut: "PAGESË",
|
||
evtAnomaly: "ANOMALI",
|
||
evtRefused: "REFUZUAR",
|
||
// rreshti i detajeve të eventit live + etiketat e klasifikimit (nga payload)
|
||
evtNoReason: "pa arsye të regjistruar",
|
||
badgeEntryRefused: "hyrje e refuzuar",
|
||
badgeExitRefused: "dalje e refuzuar",
|
||
badgeLotFull: "parkimi plot",
|
||
badgeBarrierFailed: "barriera nuk u hap",
|
||
badgeManualOpen: "hapje manuale",
|
||
badgeSubRefused: "abonimi u refuzua",
|
||
badgeSubSale: "shitje abonimi",
|
||
badgeWindowCharge: "jashtë orarit — detyrim",
|
||
badgeNoTicket: "bileta nuk u printua",
|
||
feedSourceBooth: "kabinë",
|
||
feedSourceReader: "lexues",
|
||
// dritarja e detajeve të eventit
|
||
eventDetail: "Detajet e eventit",
|
||
edType: "Lloji",
|
||
edTime: "Ora",
|
||
edIndex: "Indeksi në regjistër",
|
||
edDirection: "Drejtimi",
|
||
edSource: "Burimi",
|
||
edIdentity: "Identiteti",
|
||
edReason: "Arsyeja",
|
||
edSnapshots: "Fotot",
|
||
edPayload: "Të dhënat e nënshkruara",
|
||
edChain: "Zinxhiri",
|
||
edSignature: "Nënshkrimi",
|
||
edKeyId: "Çelësi",
|
||
edPrevHash: "Hash-i i mëparshëm",
|
||
edNoPayload: "Ky event nuk ka të dhëna shtesë.",
|
||
edCopy: "Kopjo",
|
||
edCopied: "U kopjua",
|
||
edDetails: "Detajet",
|
||
edAuditData: "Të dhënat e auditimit (nënshkrimi & zinxhiri)",
|
||
edAmount: "Shuma",
|
||
edTender: "Mënyra e pagesës",
|
||
edSession: "Sesioni",
|
||
edPlate: "Targa",
|
||
edCategory: "Kategoria",
|
||
edOperator: "Operatori",
|
||
edTariffVersion: "Versioni i tarifës",
|
||
edRawPayload: "Të dhënat e papërpunuara të nënshkruara",
|
||
edOccurrence: "ID e hyrjes",
|
||
subscriber: "Abonent",
|
||
edVia: "Mënyra e hyrjes",
|
||
viaQr: "Kod QR",
|
||
viaCard: "Kartë/çip RFID",
|
||
viaPlate: "Targë",
|
||
},
|
||
// Mesazhet e përkthyera për REASON_CODES e nënshkruara (shih @parking/shared).
|
||
// Çelësat përputhen 1:1 me kodet; {{param}} mbushet nga reasonParams i eventit.
|
||
reason: {
|
||
"entry.refused.full": "Hyrja u refuzua — parkimi plot ({{count}}/{{capacity}})",
|
||
"entry.held.noTicket": "Hyrja u mbajt — bileta nuk u printua: {{detail}}",
|
||
"exit.refused.closed": "Dalja u refuzua — sesioni është mbyllur tashmë",
|
||
"exit.refused.noSession": "Dalja u refuzua — biletë e panjohur",
|
||
"exit.refused.unpaid": "Dalja u refuzua — e papaguar (bëj pagesën në fillim)",
|
||
"exit.refused.graceExpired": "Dalja u refuzua — afati i daljes skadoi (kërkohet pagesë shtesë)",
|
||
"exit.open.noBarrier": "Dalja u regjistrua, por nuk ka barrierë daljeje të konfiguruar — hape me dorë",
|
||
"exit.open.unavailable": "Dalja u regjistrua, por barriera është e padisponueshme — hape me dorë",
|
||
"exit.open.failed": "Dalja u regjistrua, por barriera nuk u hap — hape me dorë",
|
||
"exit.freeGrace": "Periudhë pa pagesë në hyrje (pa tarifë)",
|
||
"exit.manualOpen": "Hapje manuale e barrierës (ndërhyrje njerëzore)",
|
||
"sub.refused.notFound": "Abonimi u refuzua — nuk u gjet",
|
||
"sub.refused.outOfWindow": "Abonimi u refuzua — {{status}}/jashtë afatit",
|
||
"sub.refused.noSession": "Dalje me abonim pa sesion të hapur (tashmë jashtë / nuk ka hyrë kurrë)",
|
||
"sub.refused.atCapacity": "Abonimi u refuzua — në kapacitet ({{inUse}}/{{max}} makina brenda)",
|
||
"sub.refused.unpaidWindow": "Dalja u refuzua — detyrim jashtë orarit i papaguar ({{amount}} {{currency}}); paguaje në kabinë",
|
||
"void.ticketCancelled": "Bileta u anulua — {{reason}}",
|
||
},
|
||
tariff: {
|
||
title: "Tarifa",
|
||
noRateCard: "Asnjë tarifë e publikuar — arka nuk mund të faturojë derisa të publikoni një.",
|
||
activeSince: "Aktive që nga {{date}} · {{count}} version(e) në histori. Publikimi krijon një version të ri; sesionet e kaluara ruajnë çmimin origjinal.",
|
||
currency: "Monedha",
|
||
freeEntryGrace: "Periudha pa pagesë në hyrje (min)",
|
||
billingIncrement: "Intervali i faturimit (min)",
|
||
dailyCap: "Kufiri ditor (bosh = pa kufi)",
|
||
dailyCapPh: "p.sh. 12.00",
|
||
lostTicketFee: "Tarifa për biletë të humbur",
|
||
exitGrace: "Periudha e kthimit në dalje (min)",
|
||
rateBlocks: "Blloqet tarifore",
|
||
rateBlocksHint: "Çdo brez zgjat një numër orësh dhe faturohet me çmimin e tij; brezat konsumohen me radhë (orët e para, pastaj orët në vijim). Brezi i fundit është \"më pas\" (i hapur) — çmimi i tij zbatohet pas mbarimit të shkallës. Çmimi është për interval faturimi.",
|
||
bandDuration: "Kohëzgjatja e brezit",
|
||
hoursUnit: "orë",
|
||
egHours: "p.sh. 2",
|
||
pricePerIncrement: "Çmimi / interval",
|
||
thereafter: "më pas (i hapur)",
|
||
remove: "Hiq",
|
||
addBlock: "+ Shto bllok",
|
||
publishNewVersion: "Publiko version të ri",
|
||
publishing: "Duke publikuar…",
|
||
publishedOk: "U publikua versioni i ri i tarifës — tani është tarifa aktive.",
|
||
defaultCard: "Tarifa bazë (gjithmonë aktive)",
|
||
defaultCardHint: "Çmimi bazë i zbatuar kur asnjë nivel kohor/sezonal nuk vlen. Kjo e vetme është mjaftueshëm për shumicën e parkimeve.",
|
||
modeLadder: "Shkallë orësh",
|
||
modeFlat: "Çmim fiks",
|
||
modeStepped: "Sipas kohëzgjatjes (deri-në)",
|
||
steppedHint:
|
||
"Vendos çmimin TOTAL për një qëndrim deri në një kohë të caktuar (p.sh. deri 3 orë = 500). Fiton rreshti i parë me kufi ≥ kohëzgjatjes (kufiri përfshihet). Totali i rreshtit të fundit përsëritet si çmim ditor për qëndrime më të gjata.",
|
||
stepUpTo: "Deri në",
|
||
stepTotal: "Çmimi total",
|
||
addStep: "+ Shto rresht",
|
||
steppedTiersConflict:
|
||
"⚠ Nivelet kohore/sezonale NUK zbatohen kur tarifa bazë është 'Sipas kohëzgjatjes (deri-në)' — motori i shpërfill plotësisht. Hiqi nivelet, ose ndrysho tarifën bazë në 'Shkallë orësh' a 'Çmim fiks'. Publikimi bllokohet derisa kjo të rregullohet.",
|
||
tiersAdvanced: "Të avancuara: nivele kohore & sezonale",
|
||
tiersHint: "Opsionale. Shto nivele tarifore që vlejnë vetëm në orë/ditë/data ose kategori të caktuara (p.sh. orë e lirë, tarifë nate, fundjavë, autobus). Pa nivele, publikohet vetëm tarifa bazë.",
|
||
tierName: "Emri",
|
||
tierPriority: "Përparësia",
|
||
tierCategory: "Kategoria",
|
||
tierCategoryPh: "p.sh. autobus",
|
||
tierDays: "Ditët",
|
||
tierHours: "Orët",
|
||
tierDates: "Datat",
|
||
tierOvernight: "(kalon mesnatën)",
|
||
addTier: "+ Shto nivel",
|
||
dow1: "Hën",
|
||
dow2: "Mar",
|
||
dow3: "Mër",
|
||
dow4: "Enj",
|
||
dow5: "Pre",
|
||
dow6: "Sht",
|
||
dow0: "Die",
|
||
},
|
||
setup: {
|
||
title: "Konfigurimi",
|
||
intro:
|
||
"Shto fillimisht kontrollerat e barrierave — cakto cili rele është hyrje/dalje dhe në cilin terminal është lidhur butoni i hyrjes. Pastaj shto lexues, kamera dhe printera dhe drejto secilin te barriera që shërben.",
|
||
// Category titles + the singular noun used in buttons/modal titles.
|
||
catControllers: "Kontrollerat (barrierat + butoni i hyrjes)",
|
||
catReaders: "Lexuesit (QR / RFID)",
|
||
catCameras: "Kamerat (foto + targë)",
|
||
catPrinters: "Printerat (bileta / vouchera)",
|
||
nounController: "kontroller",
|
||
nounReader: "lexues",
|
||
nounCamera: "kamerë",
|
||
nounPrinter: "printer",
|
||
add: "+ Shto {{noun}}",
|
||
addAnother: "+ Shto {{noun}}",
|
||
addTitle: "Shto {{noun}}",
|
||
editTitle: "Ndrysho {{noun}}",
|
||
needControllerFirst: "Shto fillimisht një kontroller — {{noun}} drejtohet te një prej releve të tij.",
|
||
failedToLoad: "Ngarkimi i konfigurimit dështoi: {{error}}",
|
||
loadingCatalog: "Duke ngarkuar katalogun e pajisjeve…",
|
||
// Direction labels (relay direction + inherited binding).
|
||
dirEntry: "Hyrje",
|
||
dirExit: "Dalje",
|
||
dirBoth: "Hyrje + dalje",
|
||
inherits: "trashëgon {{direction}}",
|
||
// Warnings panel.
|
||
warnTitle: "⚠ U ruajt, por nevojitet veprim:",
|
||
dismiss: "Mbyll",
|
||
// Assignment row.
|
||
disabled: "(çaktivizuar)",
|
||
edit: "Ndrysho",
|
||
remove: "Hiq",
|
||
removing: "Duke hequr…",
|
||
confirmRemove: "Të hiqet kjo pajisje {{driver}}?",
|
||
noRelaysSet: "asnjë rele e caktuar",
|
||
unbound: "e palidhur",
|
||
// Device form.
|
||
noDrivers: "Asnjë drejtues i regjistruar.",
|
||
chooseDevice: "Zgjidh një pajisje…",
|
||
scan: "Skano për kontroller",
|
||
scanning: "Duke skanuar…",
|
||
noControllersFound: "Asnjë kontroller në LAN.",
|
||
use: "Përdor",
|
||
test: "Testo lidhjen",
|
||
testing: "Duke testuar…",
|
||
saveConfigure: "Ruaj & konfiguro",
|
||
saveChanges: "Ruaj ndryshimet",
|
||
saving: "Duke ruajtur…",
|
||
cancel: "Anulo",
|
||
testFailed: "Testi dështoi: {{error}}",
|
||
saveFailed: "Ruajtja dështoi: {{error}}",
|
||
deviceLabel: "Pajisja:",
|
||
preconditionsOk: "● parakushtet OK",
|
||
autoFixedOnSave: "(rregullohet vetë në ruajtje)",
|
||
backendPushIp: "IP-ja e backend-it",
|
||
chooseAddress: "Zgjidh një adresë…",
|
||
onDeviceSubnet: "— në subnetin e pajisjes",
|
||
noNicOnSubnet: "⚠ asnjë NIC në subnetin e pajisjes — pajisja mund të mos arrijë backend-in",
|
||
backendIpHint: "Adresa te e cila kjo pajisje do të dërgojë eventet e hyrjes.",
|
||
// Relay editor.
|
||
relaysTitle: "Relet në këtë kontroller",
|
||
relaysHint:
|
||
"Çdo rele hap një barrierë. Cakto drejtimin e saj; për hyrje kalimtare, cakto në cilin terminal hyrës është lidhur butoni i hyrjes.",
|
||
outputsTitle: "Daljet — relet (barrierat + drita)",
|
||
outputsHint:
|
||
"Relet janë DALJE: secila hap një barrierë (ose ndez dritën e butonit). Cakto numrin e relesë dhe drejtimin. Terminalet hyrëse (butoni, sensori) janë te seksioni Hyrjet më poshtë.",
|
||
pulseOpenMs: "Kohëzgjatja e hapjes (ms)",
|
||
pulseOpenHint: "Sa kohë mbahet rele e barrierës e hapur (jog). Vlen për të gjitha relet e barrierave.",
|
||
inputsTitle: "Hyrjet — terminalet (buton, sensor)",
|
||
inputsHint:
|
||
"Hyrjet janë TERMINALE që hosti i LEXON: butoni i hyrjes dhe sensori i pranisë/radari. Secila i përket një barriere hyrëse — e gateron ose e nis atë rele.",
|
||
inputsIdleHigh: "Hyrjet në pushim HIGH",
|
||
inputsIdleHighHint: "Kjo pllakë i mban hyrjet HIGH në pushim (statusi 1111); një shtypje e ul në LOW.",
|
||
relay: "Rele",
|
||
// Generic input rows: terminal + role + the relay it serves.
|
||
inputTerminal: "Terminali",
|
||
inputServesRelay: "I shërben reles",
|
||
roleButton: "Butoni i hyrjes",
|
||
rolePresenceLoop: "Prania (lak induktiv)",
|
||
rolePresenceRadar: "Prania (radar)",
|
||
roleAlertTrigger: "Trigger alarmi",
|
||
addInput: "+ Shto hyrje",
|
||
entryCooldown: "Pritje pas biletës (sek)",
|
||
entryCooldownHint:
|
||
"Kur nuk ka sensor pranie: shtypjet e përsëritura të butonit shtypen për kaq sekonda pas një bilete. Zgjidhje rezervë (jo garanci) — një abuzues mund ta presë afatin.",
|
||
activeLow: "Aktiv-ulët",
|
||
activeLowHint:
|
||
"Shëno nëse sensori i pranisë (p.sh. radari) qëndron HIGH në pushim dhe shkon LOW kur detekton — e kundërta e butonit. Kjo përmbys leximin e atij terminali që 'prania' të lexohet saktë.",
|
||
eventRadarAlert: "Alarm radar (dritë)",
|
||
triggerInput: "Trigger input",
|
||
triggerInputHint:
|
||
"Terminali i hyrjes (radari) që nis pulsimin e kësaj rele. Pulson kur Trigger input është aktiv por kamera s'konfirmon makinë; ndizet fiks kur kamera konfirmon; përndryshe fiket.",
|
||
lockLane: "Bllokimi nga",
|
||
lockLaneHint:
|
||
"Cila kamerë e ndez dritën fiks: hyrja apo dalja. Një radar i daljes duhet të bllokohet nga kamera e DALJES.",
|
||
lockLaneEntry: "Kamera e hyrjes",
|
||
lockLaneExit: "Kamera e daljes",
|
||
blinkOnMs: "Pulsim ndezur (ms)",
|
||
blinkOffMs: "Pulsim fikur (ms)",
|
||
addRelay: "+ Shto rele",
|
||
// Camera ANPR opt-in.
|
||
anpr: "Njohja e targave (ANPR)",
|
||
anprHint:
|
||
"Lexo targat në këtë aparat: shërbimi i vizionit lexon targën nga çdo pamje dhe e regjistron (hyrje dhe dalje). Kërkon shërbimin e vizionit aktiv.",
|
||
anprAuto: "Hapje/mbyllje automatike me targën e abonentit",
|
||
anprAutoHint:
|
||
"Lejo që KY aparat të hapë vetë barrierën kur njeh targën e një abonenti. ÇAKTIVIZOJE te aparati i daljes në një korsi të përbashkët hyrje/dalje, që një makinë që HYN të mos DALË automatikisht nga targa e pasme (njohja vazhdon — fiket vetëm hapja automatike).",
|
||
testAnpr: "Testo ANPR",
|
||
anprTesting: "Duke testuar ANPR…",
|
||
testAnprHint:
|
||
"Merr një pamje të drejtpërdrejtë nga kjo kamerë dhe përpiqet të lexojë një targë, duke raportuar rezultatin dhe kohën e nevojshme. Vendos një targë para kamerës më parë.",
|
||
anprOk: "✓ Targa u lexua {{plate}} — {{confidence}}% besueshmëri, {{ms}} ms",
|
||
anprLowConfidence: "(besueshmëri e ulët — vetëm këshillues)",
|
||
anprTookMs: "{{ms}} ms",
|
||
"anprFail.vision-disabled": "Shërbimi i vizionit është çaktivizuar — aktivizoje (VISION_ENABLED) për ta testuar ANPR.",
|
||
"anprFail.snapshot-failed": "Nuk u mor dot pamje nga kamera (jashtë linje ose e paarritshme).",
|
||
"anprFail.no-plate": "Nuk u gjet asnjë targë në pamje.",
|
||
// Printer test slip — pushes a real slip so the admin can confirm it physically prints.
|
||
testPrint: "Printo provë",
|
||
printTesting: "Duke printuar…",
|
||
testPrintHint:
|
||
"Dërgon një fletë prove te printeri tani. ‘I lidhur’ vetëm hap lidhjen — kjo konfirmon se printeri vërtet nxjerr letër.",
|
||
printOk: "✓ Fleta e provës u dërgua ({{ms}} ms). Kontrollo printerin.",
|
||
"printFail.print-failed": "Printeri nuk pranoi punën (pa letër, kapaku hapur, ose lidhja ra).",
|
||
// Reveal/hide toggle for a secret field (e.g. the device web password).
|
||
revealSecret: "Shfaq fjalëkalimin",
|
||
hideSecret: "Fshih fjalëkalimin",
|
||
// Alarm Server push settings — generated for the camera's Event → Alarm Server form.
|
||
alarmUrlTitle: "Cilësimet e Alarm Server (vendosi te kamera)",
|
||
alarmUrlHint:
|
||
"Vendosi këto te kamera: Configuration → Event → … → Alarm Settings (ose Notify Surveillance Center). Kamera do të dërgojë çdo ngjarje këtu — pa polling.",
|
||
alarmUrlCopy: "Kopjo të gjitha",
|
||
alarmUrlCopied: "U kopjua ✓",
|
||
alarmUrlSaveFirst:
|
||
"Ruaje kamerën më parë — adresa gjenerohet pasi pajisja të marrë një ID. Hape sërish për editim që ta shohësh.",
|
||
alarmUrlTestFirst:
|
||
"Kliko “Testo lidhjen” më parë — kështu përcaktohet IP-ja e këtij hosti në rrjetin e kamerës (që kamera ta thërrasë).",
|
||
alarmFieldHost: "Destination IP / Host",
|
||
alarmFieldUrl: "URL",
|
||
alarmFieldProtocol: "Protokolli",
|
||
alarmFieldPort: "Porta",
|
||
// Binding picker.
|
||
whichBarrier: "Cilën barrierë shërben kjo pajisje?",
|
||
controller: "Kontrolleri",
|
||
choose: "Zgjidh…",
|
||
relayLabel: "Rele {{relay}} ({{direction}})",
|
||
noRelaysConfigured: "Ky kontroller nuk ka rele të konfiguruar.",
|
||
},
|
||
lab: {
|
||
title: "Lab Tarife",
|
||
intro:
|
||
"Testo tarifat në kohë (dritare ditë/natë, kufi ditor, qëndrim tej afatit) në sekonda, pa pritur orë. Çmimi llogaritet me të njëjtën logjikë si kabina; nuk shkruhet asgjë në ledger.",
|
||
loadTicket: "Ngarko nga një biletë reale",
|
||
loadTicketPh: "Numri i biletës / identiteti",
|
||
load: "Ngarko",
|
||
loaded: "U ngarkua sesioni {{id}}",
|
||
tariffVersion: "Versioni i tarifës",
|
||
activeVersion: "Versioni aktiv (i tanishëm)",
|
||
entered: "Hyrja",
|
||
asOf: "Deri më (tani/dalja)",
|
||
now: "Tani",
|
||
category: "Kategoria",
|
||
categoryPh: "p.sh. bus (bosh = makinë)",
|
||
payment: "Pagesa",
|
||
paid: "u pagua",
|
||
graceMin: "afati (min)",
|
||
price: "Llogarit çmimin",
|
||
pricing: "Duke llogaritur…",
|
||
outcome: "Rezultati",
|
||
amountDue: "Shuma për pagesë",
|
||
billedPeriod: "Periudha e faturuar",
|
||
overstay: "tej afatit",
|
||
settled: "i shlyer",
|
||
periodStart: "Fillimi i periudhës",
|
||
graceExpires: "Afati skadon",
|
||
curve: "Kurba sipas kohëzgjatjes",
|
||
curveHint: "Tarifa nga hyrja për disa kohëzgjatje — shih ku rrafshohet kufiri ditor ose ndryshojnë dritaret.",
|
||
},
|
||
subs: {
|
||
title: "Abonimet",
|
||
unnamed: "(pa emër)",
|
||
unbound: "pa kufizim",
|
||
car_one: "{{count}} makinë",
|
||
car_other: "{{count}} makina",
|
||
cred: "kredencial",
|
||
plates: "{{count}} targë(a)",
|
||
noPrice: "pa çmim",
|
||
perDay: "ditë",
|
||
perWeek: "javë",
|
||
perMonth: "muaj",
|
||
plan: "Plani",
|
||
quantity: "Makina",
|
||
quantityHint: "makina të mbuluara nga ky abonim (çmimi ×N)",
|
||
count: "Sa",
|
||
planNone: "— pa pagesë / falas —",
|
||
planNoneAvail: "Asnjë plan i përcaktuar — admini duhet të krijojë një të parin.",
|
||
version: "Versioni",
|
||
versionCurrent: "aktual",
|
||
versionHint: "Zhvendos këtë abonent në një version tjetër të të njëjtit plan. Çmimi mbetet siç u faturua; ndryshon vetëm orari i lejuar nga këtu e tutje.",
|
||
versionOnlyOne: "vetëm një version i këtij plani",
|
||
everyDay: "çdo ditë",
|
||
allDay: "24/7 (pa orar)",
|
||
quoting: "duke llogaritur…",
|
||
quotePrompt: "zgjidh datën e mbarimit",
|
||
quoteLine: "{{periods}} × {{unit}} · {{amount}} {{currency}}",
|
||
tender: "Paguar me",
|
||
tenderCash: "Para në dorë",
|
||
tenderCard: "Kartë",
|
||
tenderHint: "Regjistrohet si pagesë e nënshkruar (aktiviteti, arka, raporti i turnit).",
|
||
saleRecorded: "Shitja u regjistrua: {{amount}} {{currency}} ({{tender}}).",
|
||
saleNoShift: "⚠ Asnjë turn i hapur — hapni një që arkëtimi të hyjë në një raport turni.",
|
||
edit: "Ndrysho",
|
||
revoke: "Anulo",
|
||
delete: "Fshij",
|
||
noneYet: "Asnjë abonim ende.",
|
||
add: "+ Shto abonim",
|
||
new: "Abonim i ri",
|
||
editTitle: "Ndrysho abonimin",
|
||
holderName: "Emri i mbajtësit",
|
||
contact: "Kontakti",
|
||
carLimit: "Kufiri i makinave",
|
||
limitCarsInAtOnce: "kufizo makinat brenda njëkohësisht",
|
||
validFrom: "Vlen nga",
|
||
validTo: "Vlen deri",
|
||
validToEnd: "Vlen deri (mbarimi)",
|
||
isoDateOptional: "Datë ISO (opsionale)",
|
||
boundPlates: "Targat e lidhura",
|
||
commaSeparatedOptional: "të ndara me presje (opsionale)",
|
||
credentials: "Kredencialet",
|
||
credentialsCardQr: "Kredencialet (kartë / QR)",
|
||
rfCardTag: "Kartë/Tag RF",
|
||
rfCardTagSoon: "Kartë/Tag RF (së shpejti)",
|
||
rfPlaceholder: "numri i kartës (ose lexo kartën)",
|
||
readCard: "Lexo kartën",
|
||
captureChooseReader: "Zgjidh lexuesin, pastaj afro kartën:",
|
||
captureNoReaders: "Asnjë lexues i konfiguruar.",
|
||
captureWaiting: "Afro kartën te lexuesi…",
|
||
captureTimeout: "Skadoi pa lexuar kartë. Provo sërish.",
|
||
captured: "Karta u lexua: {{value}}",
|
||
qr: "QR",
|
||
qrAutoGen: "kodi QR gjenerohet automatikisht në ruajtje",
|
||
credentialValue: "vlera e kredencialit",
|
||
addCredential: "+ kredencial",
|
||
needCredentialOrPlate: "Një abonim kërkon të paktën një kredencial OSE një targë të lidhur.",
|
||
save: "Ruaj",
|
||
cancel: "Anulo",
|
||
saved: "Abonimi u ruajt.",
|
||
savedPrinted: "Abonimi u ruajt — kodi QR u printua.",
|
||
savedPrintFailed: "Abonimi u ruajt, por printimi dështoi ({{error}}). Përdor \"Printo kodin\".",
|
||
printCode: "Printo kodin",
|
||
printedOn: "Kodi u printua te {{printer}}.",
|
||
confirmRevoke: "Të anulohet abonimi për {{name}}? Do të refuzohet te barriera.",
|
||
confirmDelete: "Të fshihet abonimi për {{name}}? (t e kaluara ruhen.)",
|
||
statusActive: "aktiv",
|
||
statusSuspended: "pezulluar",
|
||
statusRevoked: "anuluar",
|
||
},
|
||
plans: {
|
||
title: "Planet e abonimit",
|
||
intro: "Planet i përcakton admini; operatori vetëm shet prej tyre — çmimi merret automatikisht, nuk shkruhet. Ndryshimi i një plani publikon një version të ri; shitjet e mëparshme ruajnë çmimin e tyre.",
|
||
add: "+ Shto plan",
|
||
noneYet: "Asnjë plan ende. Shto një që kabina të shesë abonime.",
|
||
colName: "Emri",
|
||
colPrice: "Çmimi",
|
||
colHours: "Orari",
|
||
colUsedBy: "Përdorur nga",
|
||
colEffective: "Vlen nga",
|
||
allHours: "24/7",
|
||
usedByCount: "{{active}} aktive / {{total}}",
|
||
usedByNone: "asnjë",
|
||
usedByTitle: "Shfaq abonimet në këtë plan",
|
||
subscribers: "Abonentët",
|
||
inForce: "në fuqi",
|
||
retired: "i tërhequr",
|
||
versionCount: "{{count}} versione",
|
||
newVersion: "Version i ri",
|
||
retire: "Tërhiq",
|
||
reactivate: "Riaktivizo",
|
||
delete: "Fshij",
|
||
deleteTitle: "Fshij këtë plan përgjithmonë (vetëm kur asnjë abonim nuk e përdor)",
|
||
reactivated: "“{{name}}” është përsëri i shitshëm.",
|
||
confirmDelete: "Të fshihet plani “{{name}}” përgjithmonë? Kjo s'mund të kthehet.",
|
||
deleted: "Plani “{{name}}” u fshi.",
|
||
deleteInUse: "S'mund të fshihet — abonime ende e përdorin këtë plan. Tërhiqe në vend të kësaj.",
|
||
newTitle: "Plan i ri",
|
||
newVersionTitle: "Publiko version të ri",
|
||
newVersionHint: "Kjo publikon një version TË RI të planit — shitjet ekzistuese ruajnë çmimin origjinal.",
|
||
period: "Periudha",
|
||
pricePer: "Çmimi për periudhë",
|
||
namePlaceholder: "p.sh. Mujor standard, ose Mujor natën, ose Hotel ditor",
|
||
needName: "Emri i planit është i detyrueshëm.",
|
||
needPrice: "Shkruaj një çmim më të madh se zero.",
|
||
saved: "Plani u ruajt.",
|
||
confirmRetire: "Të tërhiqet plani “{{name}}”? Nuk do të jetë më i shitshëm (historiku ruhet).",
|
||
needWindow: "Shkruaj orare të vlefshme (HH:MM).",
|
||
needDays: "Zgjidh të paktën një ditë për intervalin.",
|
||
restrictTimes: "Kufizo oraret e parkimit (tarifë kalimtare jashtë intervalit)",
|
||
days: "Ditët",
|
||
window: "Intervali",
|
||
enterAfter: "hyrje pas",
|
||
exitBefore: "· dalje para",
|
||
grace: "Tolerancë",
|
||
graceHint: "minuta tolerancë rreth kufijve të intervalit",
|
||
timeframesHint: "Një skanim jashtë intervalit të lejuar tarifohet me tarifën normale kalimtare për minutat jashtë intervalit (hyrja e hershme shtyhet në dalje; dalja e vonuar bllokohet derisa paguhet).",
|
||
},
|
||
site: {
|
||
occupancy: "Prania:",
|
||
noCapacitySet: "(pa kapacitet të caktuar)",
|
||
free: "lirë",
|
||
full: "PLOT",
|
||
capacityLabel: "Kapaciteti (bosh = pa kufi):",
|
||
capacityPlaceholder: "p.sh. 120",
|
||
printExitDefault: "Printo biletën e daljes si parazgjedhje",
|
||
printExitHint: "(klienti skanon biletën në dalje)",
|
||
reserveSubs: "Rezervo vendet e abonentëve",
|
||
reserveSubsHint: "Mban një vend për makinat e çdo abonenti aktiv edhe kur nuk janë të parkuar — kalimtarët e shohin 'plot' më shpejt. Joaktiv: numërohen vetëm makinat brenda (mbingarkesa menaxhohet me parkim manual).",
|
||
anprEntry: "Hapje automatike për targat e abonentëve (ANPR)",
|
||
anprEntryHint: "Kur është aktiv, targa e një abonenti e lexuar nga kamera e korsisë hap barrierën përmes portës normale të abonimit. Joaktiv: abonentët duhet të përdorin kartën/QR-në. Fotot e targave regjistrohen gjithsesi.",
|
||
parkDetails: "Të dhënat e parkimit (opsionale — shfaqen në bileta/fatura)",
|
||
save: "Ruaj",
|
||
saved: "U ruajt.",
|
||
fieldParkName: "Emri i parkimit",
|
||
fieldParkNamePh: "p.sh. Parking Aeroport",
|
||
fieldOperator: "Operatori (emri ligjor)",
|
||
fieldOperatorPh: "kompania operuese",
|
||
fieldNius: "NIUS",
|
||
fieldNiusPh: "p.sh. L01234567A",
|
||
fieldAddress: "Adresa",
|
||
fieldPhone: "Telefoni",
|
||
fieldEmail: "Email",
|
||
},
|
||
users: {
|
||
title: "Përdoruesit",
|
||
add: "+ Shto përdorues",
|
||
new: "Përdorues i ri",
|
||
none: "Asnjë përdorues.",
|
||
username: "Përdoruesi",
|
||
password: "Fjalëkalimi",
|
||
passwordHint: "Të paktën 8 karaktere.",
|
||
newPassword: "fjalëkalim i ri",
|
||
role: "Roli",
|
||
resetPassword: "Rivendos fjalëkalimin",
|
||
edit: "Ndrysho",
|
||
editTitle: "Ndrysho përdoruesin",
|
||
save: "Ruaj",
|
||
delete: "Fshi",
|
||
confirmDelete: "Të fshihet përdoruesi \"{{name}}\"?",
|
||
// Optional profile metadata.
|
||
detailsSection: "Të dhënat (opsionale)",
|
||
fullName: "Emri i plotë",
|
||
phone: "Telefoni",
|
||
email: "Email",
|
||
address: "Adresa",
|
||
},
|
||
roles: {
|
||
title: "Rolet",
|
||
add: "+ Shto rol",
|
||
new: "Rol i ri",
|
||
editTitle: "Ndrysho rolin",
|
||
name: "Emri",
|
||
permissions: "Lejet",
|
||
builtin: "i integruar",
|
||
edit: "Ndrysho",
|
||
delete: "Fshi",
|
||
confirmDelete: "Të fshihet roli \"{{name}}\"?",
|
||
permCount_one: "{{count}} leje",
|
||
permCount_other: "{{count}} leje",
|
||
userCount_one: "{{count}} përdorues",
|
||
userCount_other: "{{count}} përdorues",
|
||
},
|
||
shift: {
|
||
label: "Turni:",
|
||
open: "hapur",
|
||
notStarted: "i panisur",
|
||
since: "që nga",
|
||
startShift: "Fillo turnin",
|
||
starting: "Duke filluar…",
|
||
endShift: "Mbyll turnin",
|
||
ending: "Duke mbyllur…",
|
||
endConfirm: "Të mbyllet ky turn? Regjistrohet dhe printohet një Raport Z i nënshkruar.",
|
||
drawer: "Arka:",
|
||
openingFloatInherited: "(bilanci fillestar i trashëguar nga turni i mëparshëm)",
|
||
drawerCashAdmin: "Para në arkë (admin) — shto ose hiq bilancin",
|
||
drawerVoucher: "Mandat arke — operatori e hap, admini e autorizon",
|
||
amount: "shuma",
|
||
reasonPlaceholder: "arsyeja (p.sh. bilanci fillestar)",
|
||
load: "Shto +",
|
||
remove: "Hiq −",
|
||
authName: "përdoruesi i adminit",
|
||
authPassword: "fjalëkalimi i adminit",
|
||
authRequired: "Një admin duhet ta autorizojë: shkruaj përdoruesin dhe fjalëkalimin e tij.",
|
||
mandatArketimi: "Arkëtim (hyrje) +",
|
||
mandatPagese: "Pagesë (dalje) −",
|
||
voucherHint: "Mandat Arkëtimi shton para; Mandat Pagese heq para. Arka lëviz vetëm me autorizimin e një admini.",
|
||
voucherRecorded: "Mandati {{no}} u regjistrua. Arka tani {{amount}}.",
|
||
enterPositive: "Shkruaj një shumë pozitive.",
|
||
drawerNow: "Arka tani {{amount}}.",
|
||
zReport: "MBYLLJA E TURNIT",
|
||
viewTakings: "Arkëtimet deri tani",
|
||
xReport: "ARKËTIMET DERI TANI",
|
||
asOf: "deri më",
|
||
xReportHint: "Vetëm për shikim — asgjë nuk regjistrohet. Këto shifra nënshkruhen kur mbyllet turni.",
|
||
payments: "Pagesa:",
|
||
cash: "Para:",
|
||
card: "Kartë:",
|
||
srcTickets: "Bileta:",
|
||
srcSubscriptions: "Abonime:",
|
||
srcSubSales: "shitje",
|
||
srcSubWindow: "jashtë orarit",
|
||
drawerSection: "— Arka —",
|
||
openingFloat: "Bilanci fillestar:",
|
||
cashTaken: "Para të marra:",
|
||
cashAdded: "Para të shtuara:",
|
||
cashRemoved: "Para të hequra:",
|
||
expectedDrawer: "Gjëndje Arke:",
|
||
printedToReceipt: "Printuar te printeri i kabinës.",
|
||
recordedNoPrinter: "Regjistruar (pa printer për të printuar).",
|
||
// Header shift control + the booth shift gate.
|
||
headerNoShift: "Asnjë turn",
|
||
headerOpen: "Hap turnin",
|
||
headerClose: "Mbyll turnin",
|
||
headerHeldBy: "Turn i hapur nga {{operator}}",
|
||
headerHeldByShort: "Turni: {{operator}}",
|
||
gateTitle: "Hap një turn për të proceduar biletat",
|
||
gateBody:
|
||
"Asnjë turn nuk është i hapur. Hap turnin tënd që pagesat dhe daljet të regjistrohen te ky turn.",
|
||
gateOtherTitle: "Turni i hapur i përket një operatori tjetër",
|
||
gateOtherBody:
|
||
"{{operator}} ka një turn të hapur. Vetëm një turn mund të jetë i hapur njëkohësisht — ai duhet të mbyllë turnin para se ti të hapësh tëndin.",
|
||
openNow: "Hap turnin tani",
|
||
opening: "Duke hapur…",
|
||
},
|
||
shifts: {
|
||
title: "Historiku i turneve",
|
||
myTitle: "Turnet e mia",
|
||
none: "Asnjë turn i mbyllur.",
|
||
operator: "Operatori",
|
||
started: "Filloi",
|
||
ended: "Mbaroi",
|
||
payments: "Pagesa",
|
||
cash: "Para",
|
||
card: "Kartë",
|
||
srcTickets: "Bileta",
|
||
srcSubscriptions: "Abonime",
|
||
srcSubSales: "shitje abonimesh",
|
||
srcSubWindow: "jashtë orarit",
|
||
expectedDrawer: "Gjëndje arke",
|
||
// Filter (admin only).
|
||
filterFrom: "Nga",
|
||
filterTo: "Deri",
|
||
allOperators: "Të gjithë operatorët",
|
||
apply: "Apliko",
|
||
clear: "Pastro",
|
||
timeframe: "Periudha",
|
||
preset_yesterday: "Dje",
|
||
preset_week: "Javën e fundit",
|
||
preset_month: "Muajin e fundit",
|
||
preset_all: "Të gjitha",
|
||
preset_custom: "Zgjidh periudhë",
|
||
selectAShift: "Zgjidh një turn për të parë aktivitetin e tij.",
|
||
noActivity: "Asnjë aktivitet në këtë turn.",
|
||
current: "aktual",
|
||
// Expanded drawer detail.
|
||
drawerSection: "Arka",
|
||
openingFloat: "Bilanci fillestar",
|
||
cashTaken: "Para të marra",
|
||
cashAdded: "Para të shtuara",
|
||
cashRemoved: "Para të hequra",
|
||
loadFailed: "Ngarkimi i turneve dështoi.",
|
||
},
|
||
reports: {
|
||
title: "Raportet",
|
||
groupBy: "Grupo sipas",
|
||
exportCsv: "Eksporto CSV",
|
||
loadFailed: "Raporti nuk u ngarkua dot: {{error}}",
|
||
noData: "Nuk ka të dhëna në këtë interval.",
|
||
footnote: "Numërimet dhe paratë mblidhen nga regjistri i nënshkruar. Oraret në {{tz}}.",
|
||
preset: { today: "Sot", "7d": "7 ditë", "30d": "30 ditë", "90d": "90 ditë" },
|
||
bucket: { hour: "Orë", day: "Ditë", month: "Muaj" },
|
||
kpi: {
|
||
entries: "Hyrje",
|
||
exits: "Dalje",
|
||
revenue: "Të ardhura",
|
||
payments: "Pagesa",
|
||
avgStay: "Qëndrim mes.",
|
||
subscribers: "Abonentë",
|
||
},
|
||
chart: {
|
||
flow: "Hyrjet & daljet me kalimin e kohës",
|
||
revenue: "Të ardhurat ({{currency}})",
|
||
mix: "Përbërja e të ardhurave",
|
||
peakHours: "Hyrjet sipas orës së ditës",
|
||
breakdown: "Ndarja",
|
||
},
|
||
mix: { ticket: "Tranzit", subSales: "Abonime", subWindow: "Jashtë orarit" },
|
||
row: {
|
||
cash: "Para në dorë",
|
||
card: "Kartë",
|
||
closed: "Sesione të mbyllura",
|
||
medianStay: "Qëndrim mesatar (median)",
|
||
subActive: "Abonime aktive",
|
||
subCars: "Makina të mbuluara",
|
||
},
|
||
},
|
||
recycleBin: {
|
||
title: "Koshi",
|
||
retentionNote: "Artikujt e fshirë mbahen për {{days}} ditë, pastaj hiqen përgjithmonë.",
|
||
empty: "Asgjë e fshirë. Artikujt që fshini shfaqen këtu, të rikuperueshëm derisa të skadojnë.",
|
||
col: { type: "Lloji", item: "Artikulli", deleted: "Fshirë", actions: "" },
|
||
kind: {
|
||
user: "Përdorues",
|
||
role: "Rol",
|
||
subscription: "Abonim",
|
||
plan: "Plan",
|
||
tariff: "Tarifë",
|
||
},
|
||
restore: "Rikthe",
|
||
purge: "Fshi përfundimisht",
|
||
purgeConfirmTitle: "Të fshihet përfundimisht?",
|
||
purgeConfirmBody: "Të fshihet përgjithmonë “{{label}}”? Nuk mund të rikthehet pas kësaj.",
|
||
purgeIrreversible: "Ky veprim është i pakthyeshëm.",
|
||
},
|
||
logs: {
|
||
title: "Loget e sistemit",
|
||
refresh: "Rifresko",
|
||
level: "Niveli",
|
||
source: "Burimi",
|
||
since: "Që nga",
|
||
apply: "Apliko",
|
||
clear: "Pastro",
|
||
allLevels: "Të gjitha nivelet",
|
||
allSources: "Të gjitha burimet",
|
||
frontend: "Ndërfaqja",
|
||
backend: "Serveri",
|
||
time: "Koha",
|
||
message: "Mesazhi",
|
||
status: "Statusi",
|
||
path: "Rruga",
|
||
empty: "Asnjë regjistër.",
|
||
},
|
||
pay: {
|
||
ticket: "Bileta",
|
||
entry: "Hyrja",
|
||
now: "Tani",
|
||
duration: "Kohëzgjatja",
|
||
statusLabel: "Statusi",
|
||
paid: "PAGUAR",
|
||
unpaid: "PAPAGUAR",
|
||
overstay: "TEJ AFATIT",
|
||
overstayHint: "Sesion i mëparshëm i paguar. Klienti nuk doli brënda afatit kohor. Kërkohet pagesë për periudhën e re. Totali më poshtë është tarifa e periudhës së re.",
|
||
topUp: "Periudha e re për pagesë",
|
||
total: "Totali",
|
||
noTariff: "pa tarifë",
|
||
tender: "Mënyra",
|
||
cash: "Para",
|
||
card: "Kartë",
|
||
printExitVoucher: "Printo biletë dalje",
|
||
selfExitHint: "(klienti del vetë te dalja)",
|
||
payAndOpen: "Paguaj + hap barrierën",
|
||
payAndVoucher: "Paguaj + printo biletën",
|
||
openBarrier: "Hap barrierën",
|
||
printVoucher: "Printo biletën",
|
||
takingPayment: "Duke marrë pagesën…",
|
||
printingVoucher: "Duke printuar biletën…",
|
||
opening: "Duke hapur…",
|
||
noSessionFound: "Nuk u gjet asnjë sesion për këtë biletë.",
|
||
alreadyClosed: "Ky sesion është mbyllur tashmë (doli {{time}}).",
|
||
lookingUp: "Duke kërkuar…",
|
||
paidBarrierOpened: "Paguar — barriera u hap. Automjeti mund të dalë.",
|
||
paidExitRecorded: "Paguar dhe dalja u regjistrua, por barriera nuk u hap: {{reason}}.",
|
||
subscription: "ABONIM",
|
||
plan: "Plani",
|
||
prepaid: "I PARAPAGUAR",
|
||
subAssistHint: "Abonim i parapaguar. Hap barrierën për të ndihmuar daljen (lexues me defekt / kartë e munguar). S'ka pagesë.",
|
||
assistOpenReveal: "Ndihmë për hapje (lexues me defekt / kartë e humbur)…",
|
||
payWindowCharge: "Merr pagesën",
|
||
windowPaidHint: "Pagesa jashtë orarit u krye. Hap barrierën që abonenti të dalë.",
|
||
windowCharge: "JASHTË ORARIT",
|
||
windowChargeHint: "Ky abonent parkoi jashtë orarit të lejuar të planit. Detyrohet të paguajë tarifën kalimtare për kohën jashtë orarit — merr pagesën, pastaj hap barrierën.",
|
||
subBarrierOpened: "Barriera u hap për abonentin (ndërhyrje e regjistruar).",
|
||
voucherPrinted: "Bileta e daljes u printua në {{printer}}. Klienti del vetë te dalja.",
|
||
// payment receipt (transparency slip)
|
||
receiptPrintFailed: "(fatura nuk u printua — provoni \"Riprinto faturën\".)",
|
||
receiptReprinted: "Fatura u riprintua në {{printer}}.",
|
||
reprintReceipt: "Riprinto faturën",
|
||
reprinting: "duke printuar…",
|
||
cancelTicket: "Anulo biletën",
|
||
cancelTicketTitle: "Anulo këtë biletë",
|
||
cancelTicketHint: "Anulon një biletë të printuar gabimisht. Ruhet një gjurmë e nënshkruar (operatori + arsyeja); hyrja origjinale nuk fshihet kurrë.",
|
||
cancelReason: {
|
||
misprint: "Printim i gabuar",
|
||
test: "Test",
|
||
wrongVehicle: "Automjet i gabuar",
|
||
},
|
||
cancelReasonPlaceholder: "Arsyeja e anulimit (e detyrueshme)…",
|
||
confirmCancelTicket: "Konfirmo anulimin",
|
||
cancelling: "duke anuluar…",
|
||
ticketCancelled: "Bileta u anulua.",
|
||
// snapshots
|
||
noSnapshots: "asnjë foto",
|
||
loadingSnapshots: "duke ngarkuar fotot…",
|
||
snapEntry: "hyrje",
|
||
snapExit: "dalje",
|
||
snapFailed: "kamera e paarritshme",
|
||
plate: "Targa",
|
||
},
|
||
};
|
||
|
||
// The catalog SHAPE (keys + nesting), with string-typed values — so en.ts must
|
||
// supply every key but may differ in value. (Not `typeof sq` with `as const`, which
|
||
// would pin en.ts to the Albanian literals.)
|
||
type Stringify<T> = { [K in keyof T]: T[K] extends object ? Stringify<T[K]> : string };
|
||
export type Catalog = Stringify<typeof sq>;
|