Skip to content

Ідентифікатори ​

Кожен запис має id. На нього посилаються інші записи, ваша база даних і ваші URL, тож id має бути правильним з першого разу, а потім ніколи не змінюватися. Ця сторінка викладає правила, пояснює, навіщо існує кожне з них, і що відбувається, коли закон змінює те, що id називає.

Правила ​

  1. Кожен запис має поле id, унікальне в межах свого набору даних. Узагальнений код (індекс, кеш, форма) обробляє всі набори даних однаково.
  2. Офіційний код має перевагу, якщо він охоплює всі записи. Якщо органи влади присвоюють код кожному запису набору даних, id і є цим кодом: громади використовують свій код REFNIS від Statbel (44021 для Gent). Код, що охоплює лише частину записів, натомість зберігається як поле: суди мають свої коди ECLI в ecli, фламандські justitiehuizen — свій номер OVO в ovo (див. чому).
  3. Інакше — ASCII у kebab-case нижнього регістру: ^[a-z0-9]+(-[a-z0-9]+)*$, побудований за допомогою scripts/id.ts: діакритику відкинуто, а все інше, що не є літерою чи цифрою, стає одним дефісом. Merelbeke-Melle → merelbeke-melle, Braine-l'Alleud → braine-l-alleud, Liège → liege.
  4. З офіційної назви місцевою мовою: нідерландською у Фландрії, французькою у Валлонії, німецькою в районі Eupen. Брюссель офіційно двомовний і потребує одного фіксованого вибору: нідерландська.
  5. Номер — це суфікс: місця з кількома кантонами отримують gent-1 … gent-5.
  6. Суди — це type + місце: justice-of-the-peace-gent-1, court-of-appeal-liege. Vredegerecht / justice de paix бере id свого кантону. Два суди одного типу в Брюсселі, по одному на кожну мову, додають -nl або -fr (police-court-brussel-fr). Відділення чи місце засідань додає своє місце до id свого суду (enterprise-court-gent-brugge). Префікс зберігає унікальність id, коли в Gent є vredegerecht, ondernemingsrechtbank і arbeidsrechtbank, і він точно збігається з type запису, тож другий словник ніколи не потрібен.
  7. В'язниці та justitiehuizen / maisons de justice — це їхня назва місцевою мовою, без артиклів: gevangenis-gent, prison-lantin, justitiehuis-gent, maison-justice-arlon. Їхні назви вже кажуть, чим вони є, а дві установи в одному місті (центральна і допоміжна в'язниці Leuven) різняться назвою.
  8. Зв'язки — це поля, а не похідні рядки. Vredegerecht має поле canton; кантон перелічує { municipality }; судовий округ має judicialArea. Кожне з них містить id запису, на який вказує, а поле назване за набором даних, на який воно посилається.

Усе це забезпечують тести (test/ids.test.ts) і JSON Schemas, які перелічують допустимі id, тож висяче посилання не проходить валідацію.

Id ​

Набір данихПрикладиПравило
Апеляційні округиantwerpen, brussel, gent, liege, monsМісцева назва
Судові округиoost-vlaanderen, brabant-wallon, eupenМісцева назва
Кантониgent-1, merelbeke-melle, wavre-1, oudergem, eupen-sankt-vith-1Місцева назва + номер
Межі кантонівgent-1: одна межа на кантон, з id кантону, і canton як зв'язокId кантону
Громади44021, 21004Код REFNIS
Провінції10000, 40000Код REFNIS
Регіони02000, 03000, 04000Код REFNIS
Поштові індекси9000-44021, 1040-21005Поштовий індекс + код REFNIS
Судиjustice-of-the-peace-gent-1, enterprise-court-gent-brugge, police-court-brussel-fr, police-court-eupen-sankt-vithТип + місце
В'язниціgevangenis-gent, prison-lantin, detentiehuis-kortrijkМісцева назва
Justitiehuizen / maisons de justicejustitiehuis-gent, maison-justice-arlonМісцева назва
Процентні ставкиlegal, commercialФіксовані ключі

Чому саме такий вибір ​

Чому kebab-case? Id потрапляють в URL (/cantons/gent-1), імена файлів, CSS-класи, ключі баз даних і рядки журналів. Нижній регістр уникає колізій у системах, нечутливих до регістру (файлові системи macOS і Windows, багато collation у базах даних): Gent1 і gent1 були б двома id у даних і одним файлом на диску. Дефіси зберігають межі слів читабельними без великих літер, а набір символів ніде не потребує екранування.

Чому читабельні id, а не числа чи UUID? Довідковий набір даних читають люди: justice-of-the-peace-gent-1 у рядку бази даних чи в повідомленні про помилку одразу каже, що це. Id так само стабільні, як були б числа, бо змінюються лише тоді, коли закон змінює те, що вони називають (див. нижче), і тоді новий id — правильний результат.

Чому місцевою мовою, а не англійською? Англійські назви існують для кількох місць (Ghent, Antwerp, Liege), але не для 162 кантонів, тож англійські id означали б два правила. Місцева назва — це ще й та, якою користується сама установа, і саме вона стоїть в офіційних текстах.

Чому офіційні коди? REFNIS використовують Statbel, регіони і майже кожен бельгійський набір даних. Коли код є id, поєднати будь-який із них із кантонами й судами можна без таблиці відповідності.

Чому два коди для поштового індексу? Сам поштовий індекс не визначає запис: 1040 належить до Brussel і до Etterbeek, і кожна пара — окремий запис зі своїм періодом чинності. Пара офіційних кодів, 1040-21005, унікальна і залишається незмінною, доки таблиця Statbel не змінить пару, а саме тоді новий запис і є правильним. Громада також є полем (municipality), як вимагає правило 8: id — це ключ, а не те, що слід розбирати на частини.

Чому type в id судів? В одному місці є кілька судів, і типів судів ставатиме більше (politierechtbanken, arbeidsrechtbanken, rechtbanken van eerste aanleg…). Власні поля суду кажуть, що він таке; id лише має бути унікальним і впізнаваним, і тип забезпечує і те, і те.

Чому не офіційні коди судів? Суди мають два офіційні коди, і жоден не охоплює всіх судів. Коди ECLI (HBGNT для hof van beroep у Gent) існують для кожного суду і кожної мови, але не для відділень, і в опублікованих рішеннях vredegerechten / justices de paix їх немає зовсім. Номери підприємств (KBO) належать FOD Justitie / SPF Justice (федеральному міністерству юстиції); його виробничі одиниці (establishment units) прив'язані до будівель, а не до судів, і змінюються, коли суд переїжджає. Правило, що діє для кожного запису, краще за два правила, тож коди ECLI — це поле (ecli), а id підпорядковується правилу 6.

Чому явні зв'язки? Стара схема будувала id суду, склеюючи Vredegerecht та id кантону. Так зв'язок ховається у форматі рядка, який ламається, щойно один суд обслуговує два кантони або змінюється назва. Поле canton перевіряють схема і тести, і ним можна йти в обох напрямках.

У TypeScript ​

Кожен набір даних має згенерований тип id (CantonId, CourtId, MunicipalityId, ProvinceId, RegionId, ArrondissementId, JudicialAreaId, PrisonId, HouseOfJusticeId, PostalCodeId), який перегенеровується з даних командою pnpm build:ids:

ts
import { getCanton, type CantonId } from 'belgica'

getCanton('gent-1') // Canton: відомий id завжди знаходить свій запис
getCanton(userInput) // Canton | undefined: будь-який інший рядок може й не знайти

const id: CantonId = 'gent1' // помилка компіляції: це не id кантону

Використовуйте типи id для значень, які ви зберігаєте, щоб друкарську помилку чи видалений id було виявлено під час оновлення.

Коли закон змінює id ​

Кантони й громади справді змінюються: громади об'єднувалися у 2019 і 2025 роках, а закони перекроюють кантони. Записи мають період чинності (validFrom, validTo), тож зміна додає історію, а не стирає її:

  1. Старий запис залишається, з validTo; новий отримує новий id і validFrom. Id ніколи не використовується повторно для іншої речі, тож id, збережений роки тому, і далі знаходить те, що він означав.
  2. Без дня пошук відповідає на сьогодні: пошук за id дає версію, яка діє сьогодні (для запису, що припинився, — останню), а списки, як-от getCantonsForMunicipality, — лише те, що діє сьогодні. З { on } обидва відповідають на той день.
  3. Changelog перелічує кожен новий id і id, які він замінює.

Сама лише зміна назви, наприклад виправлення написання, не змінює id. Історії до 1 січня 2025 року в даних поки немає (#27): пошук на раніший день викидає RangeError, а не відповідає сьогоднішньою картою.

Id непрозорі ​

Id — це ключ, а не формат. court-of-first-instance-luxembourg-marche-en-famenne неможливо розкласти назад на тип, місце і відділення, бо тип, місце і мовний суфікс використовують той самий дефіс. Не розбирайте id: кожна його частина також є полем (type, court, canton, arrondissement), і саме поля перевіряють схеми й тести.

Стабільність ​

Id — це публічний API. Додавання записів — minor-версія, виправлення значення — patch, а видалення чи перейменування id — major-версія. Версія 0.3.0 замінює попередні id у PascalCase (VredegerechtGent1, EastFlanders) цією схемою ще до того, як пакет мав користувачів; changelog містить відповідність.

Цю обіцянку перевіряють, а не просто дають. ids.lock.json перелічує кожен id, який пакет коли-небудь опублікував, для кожного набору даних; pnpm generate додає до нього нові id і ніколи не видаляє жодного, а test/ids.test.ts падає, коли зафіксованого id немає в даних. Тож scraper, який читає сторінку з новим заголовком, перегенерований список кантонів чи ручна правка не можуть непомітно відкинути чи перейменувати id: щотижневий pull request із даними падає, і людина зіставляє нову назву з наявним id у парсері або завершує запис через validTo. Вилучення id із lock-файлу — свідомий крок, для major-версії, з id та його заміною в changelog.

Код за ліцензією MIT, дані за CC BY 4.0. Це довідкові дані, а не юридична консультація: перевіряйте офіційні джерела.