vehicles 0.6.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +164 -0
  3. data/CHANGELOG.md +274 -0
  4. data/README.md +55 -10
  5. data/data/PROVENANCE-vehicles.md +12 -0
  6. data/data/plates/PROVENANCE.md +5 -4
  7. data/data/plates/_decode/at-districts.yml +287 -0
  8. data/data/plates/_decode/ch-cantons.yml +110 -0
  9. data/data/plates/_decode/cn-issuing-offices.yml +463 -0
  10. data/data/plates/_decode/cn-provinces.yml +614 -0
  11. data/data/plates/_decode/cz-kraj.yml +159 -0
  12. data/data/plates/_decode/dk-serial-blocks.yml +327 -0
  13. data/data/plates/_decode/fr-departements.yml +191 -0
  14. data/data/plates/_decode/gb-age-identifiers.yml +170 -0
  15. data/data/plates/_decode/gb-memory-tags.yml +202 -0
  16. data/data/plates/_decode/gr-prefectures.yml +1408 -0
  17. data/data/plates/_decode/hr-cities.yml +315 -0
  18. data/data/plates/_decode/ie-counties.yml +227 -0
  19. data/data/plates/_decode/in-state-codes.yml +169 -0
  20. data/data/plates/_decode/is-districts-1938.yml +116 -0
  21. data/data/plates/_decode/it-provinces.yml +348 -0
  22. data/data/plates/_decode/jp-office-marks.yml +960 -0
  23. data/data/plates/_decode/jp-use-marks.yml +205 -0
  24. data/data/plates/_decode/kr-authority-marks.yml +146 -0
  25. data/data/plates/_decode/kr-use-syllables.yml +194 -0
  26. data/data/plates/_decode/lu-series-order.yml +638 -0
  27. data/data/plates/_decode/mx-entity-series.yml +380 -0
  28. data/data/plates/_decode/my-index-marks.yml +271 -0
  29. data/data/plates/_decode/no-counties-1913.yml +148 -0
  30. data/data/plates/_decode/no-districts.yml +901 -0
  31. data/data/plates/_decode/pl-powiats.yml +567 -0
  32. data/data/plates/_decode/pt-trailer-services.yml +96 -0
  33. data/data/plates/_decode/ro-counties.yml +213 -0
  34. data/data/plates/_decode/se-diplomatic.yml +220 -0
  35. data/data/plates/_decode/si-regions.yml +123 -0
  36. data/data/plates/_decode/sk-districts.yml +314 -0
  37. data/data/plates/_decode/th-registration-elements.yml +208 -0
  38. data/data/plates/_decode/ua-regions.yml +393 -0
  39. data/data/plates/_decode/za-licence-marks.yml +215 -0
  40. data/data/plates/_meta/classes.yml +1 -0
  41. data/data/plates/_meta/separators.yml +102 -0
  42. data/data/plates/ad.yml +961 -0
  43. data/data/plates/ar.yml +762 -0
  44. data/data/plates/at.yml +1424 -0
  45. data/data/plates/au-act.yml +472 -0
  46. data/data/plates/au-nsw.yml +282 -0
  47. data/data/plates/au-nt.yml +431 -0
  48. data/data/plates/au-qld.yml +272 -0
  49. data/data/plates/au-sa.yml +248 -0
  50. data/data/plates/au-tas.yml +302 -0
  51. data/data/plates/au-vic.yml +215 -0
  52. data/data/plates/au-wa.yml +309 -0
  53. data/data/plates/be.yml +1840 -0
  54. data/data/plates/br.yml +1152 -0
  55. data/data/plates/ca-ab.yml +430 -0
  56. data/data/plates/ca-bc.yml +697 -0
  57. data/data/plates/ca-mb.yml +499 -0
  58. data/data/plates/ca-nb.yml +537 -0
  59. data/data/plates/ca-nl.yml +743 -0
  60. data/data/plates/ca-ns.yml +808 -0
  61. data/data/plates/ca-nt.yml +610 -0
  62. data/data/plates/ca-nu.yml +280 -0
  63. data/data/plates/ca-on.yml +881 -0
  64. data/data/plates/ca-pe.yml +592 -0
  65. data/data/plates/ca-qc.yml +1036 -0
  66. data/data/plates/ca-sk.yml +256 -0
  67. data/data/plates/ca-yt.yml +656 -0
  68. data/data/plates/ch.yml +1273 -0
  69. data/data/plates/cn.yml +1431 -0
  70. data/data/plates/cy.yml +688 -0
  71. data/data/plates/cz.yml +1179 -0
  72. data/data/plates/de.yml +553 -118
  73. data/data/plates/dk.yml +1647 -0
  74. data/data/plates/ee.yml +1275 -0
  75. data/data/plates/es.yml +228 -32
  76. data/data/plates/fi.yml +1271 -0
  77. data/data/plates/fr.yml +1265 -0
  78. data/data/plates/gb.yml +1188 -0
  79. data/data/plates/gr.yml +721 -0
  80. data/data/plates/hr.yml +860 -0
  81. data/data/plates/hu.yml +959 -0
  82. data/data/plates/ie.yml +775 -0
  83. data/data/plates/in.yml +1172 -0
  84. data/data/plates/is.yml +667 -0
  85. data/data/plates/it.yml +1317 -0
  86. data/data/plates/jp.yml +3650 -0
  87. data/data/plates/kr.yml +1375 -0
  88. data/data/plates/li.yml +1010 -0
  89. data/data/plates/lt.yml +879 -0
  90. data/data/plates/lu.yml +842 -0
  91. data/data/plates/lv.yml +924 -0
  92. data/data/plates/mc.yml +1024 -0
  93. data/data/plates/mt.yml +854 -0
  94. data/data/plates/mx.yml +1372 -0
  95. data/data/plates/my.yml +685 -0
  96. data/data/plates/nl.yml +44 -0
  97. data/data/plates/no.yml +1018 -0
  98. data/data/plates/nz.yml +1699 -0
  99. data/data/plates/pl.yml +1296 -0
  100. data/data/plates/pt.yml +847 -0
  101. data/data/plates/ro.yml +785 -0
  102. data/data/plates/se.yml +1091 -0
  103. data/data/plates/si.yml +1105 -0
  104. data/data/plates/sk.yml +1439 -0
  105. data/data/plates/sm.yml +1119 -0
  106. data/data/plates/th.yml +1150 -0
  107. data/data/plates/ua.yml +1672 -0
  108. data/data/plates/us-ak.yml +763 -0
  109. data/data/plates/us-al.yml +457 -0
  110. data/data/plates/us-ar.yml +427 -0
  111. data/data/plates/us-as.yml +454 -0
  112. data/data/plates/us-az.yml +430 -0
  113. data/data/plates/us-ca.yml +892 -0
  114. data/data/plates/us-co.yml +452 -0
  115. data/data/plates/us-ct.yml +427 -0
  116. data/data/plates/us-dc.yml +614 -0
  117. data/data/plates/us-de.yml +551 -0
  118. data/data/plates/us-fl.yml +319 -96
  119. data/data/plates/us-ga.yml +644 -0
  120. data/data/plates/us-gu.yml +658 -0
  121. data/data/plates/us-hi.yml +585 -0
  122. data/data/plates/us-ia.yml +438 -0
  123. data/data/plates/us-id.yml +531 -0
  124. data/data/plates/us-il.yml +516 -0
  125. data/data/plates/us-in.yml +324 -0
  126. data/data/plates/us-ks.yml +351 -0
  127. data/data/plates/us-ky.yml +770 -0
  128. data/data/plates/us-la.yml +568 -0
  129. data/data/plates/us-ma.yml +379 -0
  130. data/data/plates/us-md.yml +536 -0
  131. data/data/plates/us-me.yml +445 -0
  132. data/data/plates/us-mi.yml +408 -0
  133. data/data/plates/us-mn.yml +411 -0
  134. data/data/plates/us-mo.yml +356 -0
  135. data/data/plates/us-mp.yml +402 -0
  136. data/data/plates/us-ms.yml +432 -0
  137. data/data/plates/us-mt.yml +619 -0
  138. data/data/plates/us-nc.yml +602 -0
  139. data/data/plates/us-nd.yml +419 -0
  140. data/data/plates/us-ne.yml +483 -0
  141. data/data/plates/us-nh.yml +394 -0
  142. data/data/plates/us-nj.yml +547 -0
  143. data/data/plates/us-nm.yml +574 -0
  144. data/data/plates/us-nv.yml +655 -0
  145. data/data/plates/us-ny.yml +592 -0
  146. data/data/plates/us-oh.yml +404 -0
  147. data/data/plates/us-ok.yml +513 -0
  148. data/data/plates/us-or.yml +392 -0
  149. data/data/plates/us-pa.yml +506 -0
  150. data/data/plates/us-pr.yml +507 -0
  151. data/data/plates/us-ri.yml +445 -0
  152. data/data/plates/us-sc.yml +605 -0
  153. data/data/plates/us-sd.yml +428 -0
  154. data/data/plates/us-tn.yml +471 -0
  155. data/data/plates/us-tx.yml +535 -0
  156. data/data/plates/us-ut.yml +384 -0
  157. data/data/plates/us-va.yml +567 -0
  158. data/data/plates/us-vi.yml +489 -0
  159. data/data/plates/us-vt.yml +458 -0
  160. data/data/plates/us-wa.yml +484 -0
  161. data/data/plates/us-wi.yml +509 -0
  162. data/data/plates/us-wv.yml +446 -0
  163. data/data/plates/us-wy.yml +523 -0
  164. data/data/plates/va.yml +604 -0
  165. data/data/plates/za.yml +1141 -0
  166. data/data/vehicles.json +160653 -105090
  167. data/lib/vehicles/configuration.rb +17 -3
  168. data/lib/vehicles/dataset.rb +73 -18
  169. data/lib/vehicles/fuzzy.rb +115 -0
  170. data/lib/vehicles/http.rb +48 -0
  171. data/lib/vehicles/make.rb +36 -6
  172. data/lib/vehicles/mcp_server.rb +5 -5
  173. data/lib/vehicles/model.rb +21 -2
  174. data/lib/vehicles/plates/series.rb +172 -18
  175. data/lib/vehicles/plates/template_fill.rb +188 -0
  176. data/lib/vehicles/plates/templates.rb +162 -0
  177. data/lib/vehicles/plates.rb +12 -0
  178. data/lib/vehicles/providers/hosted_provider.rb +28 -55
  179. data/lib/vehicles/validators/vehicle_make_validator.rb +3 -1
  180. data/lib/vehicles/validators/vehicle_model_validator.rb +1 -1
  181. data/lib/vehicles/version.rb +1 -1
  182. data/lib/vehicles.rb +32 -16
  183. data/rakelib/data_refresh.rake +109 -0
  184. data/rakelib/plates_refresh.rake +29 -0
  185. data/sig/vehicles.rbs +18 -0
  186. metadata +164 -2
@@ -0,0 +1,393 @@
1
+ # plates/_decode/ua-regions.yml — the Ukrainian region encodings.
2
+ #
3
+ # THE SOURCE FINDING, and it is the Anlage-5d case rather than the German one:
4
+ # BOTH CODE TABLES ARE INSIDE THE INSTRUMENT. Розділ III п. 3 of the ВИМОГИ до
5
+ # номерних знаків транспортних засобів (наказ МВС від 02.03.2021 № 166,
6
+ # z0353-21), verbatim: "Літеросполуки, які позначають адміністративно-
7
+ # територіальну належність місця реєстрації транспортного засобу, наведені в
8
+ # додатку 4 до цих Вимог." And п. 5: "Коди, які позначають адміністративно-
9
+ # територіальну належність місця реєстрації транспортного засобу, наведені в
10
+ # додатку 6 до цих Вимог." Every row below is extracted MECHANICALLY from
11
+ # Додаток 4 and Додаток 6 of the consolidated text as published on
12
+ # zakon.rada.gov.ua — not transcribed by hand and not taken from any secondary
13
+ # compilation. 27 regions, 108 letter pairs, no duplicates (computed).
14
+ #
15
+ # ---------------------------------------------------------------------------
16
+ # TWO ENCODINGS, DIFFERENT PLATES. Read this before decoding anything.
17
+ # ---------------------------------------------------------------------------
18
+ # * `annex_4_codes` — a TWO-LETTER pair. Used on types 1, 5, 12-17 and subtypes
19
+ # 3-1, 3-2, 8-2 (Розділ III п. 3). This is the pair on the LEFT of an
20
+ # ordinary car plate.
21
+ # * `annex_6_numeric` — a TWO-DIGIT code. Used on types 2, 6, 7, 11 and subtype
22
+ # 3-3 (Розділ III п. 5). This is the small number on a red transit plate, a
23
+ # police plate or an owner-ordered plate.
24
+ # A consumer that treats them as one table will decode "11" as Kyiv on a police
25
+ # plate and as nothing at all on a car plate, which is correct — and will decode
26
+ # "КА" as Kyiv on a car plate and as nothing on a police plate, also correct.
27
+ # The two never appear on the same plate.
28
+ #
29
+ # ---------------------------------------------------------------------------
30
+ # THE SCRIPT PROBLEM — recorded, never folded away (PRD-PLATES §2.6).
31
+ # ---------------------------------------------------------------------------
32
+ script:
33
+ printed: Cyrillic (Ukrainian)
34
+ finding: >-
35
+ Every letter of Додаток 4 is CYRILLIC. Measured from the published HTML, the
36
+ annex uses exactly twelve codepoints and no others:
37
+ І U+0406 · А U+0410 · В U+0412 · Е U+0415 · К U+041A · М U+041C ·
38
+ Н U+041D · О U+041E · Р U+0420 · С U+0421 · Т U+0422 · Х U+0425.
39
+ Those are the "letters of the Ukrainian alphabet that coincide in writing
40
+ with letters of the Latin alphabet" that Розділ III п. 9 requires, and the
41
+ restriction exists so that a Ukrainian plate is readable abroad.
42
+ fold: >-
43
+ `annex_4_codes_ascii` is the fold BY GLYPH SHAPE, not by sound:
44
+ І->I А->A В->B Е->E К->K М->M Н->H О->O Р->P С->C Т->T Х->X.
45
+ It is injective over the twelve, so the fold is reversible and the reverse
46
+ map is the list above. Both forms are recorded on every row; neither is
47
+ substituted for the other anywhere in this dataset.
48
+ fold_traps: >-
49
+ Cyrillic В reads B and NEVER V. Cyrillic Н reads H and NEVER N. Cyrillic Р
50
+ reads P and NEVER R. Cyrillic С reads C and NEVER S. Getting any of the four
51
+ wrong silently relabels a region: Луганська ВВ would become "VV", Одеська ВН
52
+ would become "VN", Запорізька АР would become "AR" and Львівська ВС would
53
+ become "VS" — none of which is a Ukrainian code at all. A phonetic
54
+ transliteration of these codes is always wrong.
55
+ ascii_collision_check: >-
56
+ Computed: the 108 folded pairs contain no duplicates, so the fold is
57
+ collision-free WITHIN the current table. It is NOT collision-free against
58
+ history — see `superseded_systems` below, where the 1995-2004 letter series
59
+ reused many of the same pairs against a different region map.
60
+
61
+ # ---------------------------------------------------------------------------
62
+ # THE CAVEATS THAT MAKE THIS TABLE HONEST.
63
+ # ---------------------------------------------------------------------------
64
+ decodes_to: >-
65
+ The region whose territorial МВС service centre issued THIS COMBINATION, at
66
+ the moment of issue. Ст. 34 of the Закон «Про дорожній рух» assigns the
67
+ combination on registration, and постанова КМУ від 07.09.1998 № 1388 makes
68
+ the service centre of the place of registration the issuer.
69
+ does_not_decode_to: >-
70
+ Where the vehicle is now; where its CURRENT owner lives; or where it was
71
+ registered most recently. Постанова КМУ № 1388 lets an owner keep a
72
+ буквено-цифрова комбінація in storage on deregistration and re-attach it to
73
+ another of that owner's vehicles, so a combination outlives the registration
74
+ that produced it. Treat the code as region-at-issue and nothing else.
75
+ caveat_online_registration:
76
+ date: "2022-12-12"
77
+ instrument: "Наказ МВС № 814 від 12.12.2022, amending Розділ III п. 1 of the Вимоги"
78
+ what_changed: >-
79
+ A vehicle "зареєстрован[ий] на підставі договору, укладеного в електронній
80
+ формі у визначеному законодавством порядку" carries NO region code at all.
81
+ In the region slot it carries one of four літеросполуки that identify the
82
+ CHANNEL of registration instead of a place.
83
+ effect_on_this_table: >-
84
+ A left-hand pair must be tested against `online_registration_codes` FIRST.
85
+ If it matches, the plate carries no geographic information whatsoever and a
86
+ parse API must return "no region" rather than "unknown region".
87
+ caveat_choice_of_combination:
88
+ date: "2023-06-30"
89
+ what_changed: >-
90
+ The Cabinet of Ministers amended the plate-assignment rules to let an owner
91
+ CHOOSE the plate or its letter-and-digit combination at registration. The
92
+ region pair is still issued by the registering service centre, but the
93
+ running number inside it is no longer allocated strictly in sequence, so
94
+ the ordinal carries no reliable date signal after this point.
95
+ evidence: secondary-dated
96
+ source: "https://biz.liga.net/ua/all/avto/novosti/avtovladeltsam-razreshili-vybirat-nomera-pri-registratsii-avto # 2023-07-01. Secondary; the amending постанова КМУ was not pinned in this pass"
97
+ caveat_occupied_territories: >-
98
+ Crimea (UA-43), Sevastopol (UA-40) and parts of Donetsk, Luhansk, Zaporizhzhia
99
+ and Kherson oblasts are under Russian occupation. Their codes REMAIN IN
100
+ Додаток 4 and Додаток 6 of the instrument in force on 16 December 2025, and
101
+ are recorded here exactly as the instrument carries them. Ukraine continues to
102
+ register vehicles from those regions through relocated service centres, so a
103
+ Crimean or Sevastopol code on a plate issued after 2014 does not locate the
104
+ vehicle in Crimea or Sevastopol. This table states the instrument; it makes no
105
+ claim about where any vehicle is.
106
+
107
+ # ---------------------------------------------------------------------------
108
+ jurisdiction: ua
109
+ topic: regions
110
+ authority:
111
+ name: "ВИМОГИ до номерних знаків транспортних засобів, Додаток 4 (літеросполуки) and Додаток 6 (коди) — Міністерство внутрішніх справ України"
112
+ url: "https://zakon.rada.gov.ua/laws/show/z0353-21"
113
+ sources:
114
+ - "https://zakon.rada.gov.ua/laws/show/z0353-21 # Наказ МВС від 02.03.2021 № 166, ВИМОГИ, Додаток 4 «ЛІТЕРОСПОЛУКИ, які позначають адміністративно-територіальну належність місця реєстрації транспортного засобу» (27 rows x 4 pairs, extracted mechanically) and Додаток 6 «КОДИ ...» (01-27, Kyiv 11 and 31); Розділ III пп. 1, 3, 5, 6. Consolidated text, revision 16.12.2025. Accessed 2026-08-03"
115
+ - "https://zakon.rada.gov.ua/laws/show/1388-98-п # постанова КМУ від 07.09.1998 № 1388, Порядок державної реєстрації — the issuer of the combination and the owner's right to store and re-attach it. Accessed 2026-08-03"
116
+ - "http://www.infocar.com.ua/law_ukr/law_22.html # ДСТУ 4278:2004, Додаток Б — the 2004 letter table (27 regions + the загальнодержавна pair ІІ) used for `superseded_systems`. Verbatim reproduction of the national standard. Accessed 2026-08-03"
117
+ - "https://uk.wikipedia.org/wiki/Номерні_знаки_України # the ERA ATTRIBUTION of the four Додаток 4 columns and the 1995-2004 numeric-code system. secondary-wikipedia; accessed 2026-08-03"
118
+ period: { start: 2021 }
119
+ period_evidence: enabling-instrument
120
+ period_note: >-
121
+ 2021 is the date of the INSTRUMENT that currently carries the tables, not the
122
+ date the codes began. The first column of Додаток 4 is the 2004 set, which has
123
+ been in continuous use since ДСТУ 4278:2004 came into force on 20 February
124
+ 2004; the annex was last amended by Наказ МВС № 354 від 27.04.2023. Per-code
125
+ start dates are NOT asserted — see `column_eras` for why.
126
+
127
+ # ---------------------------------------------------------------------------
128
+ # THE COLUMN QUESTION — the one place this table refuses to state a fact.
129
+ # ---------------------------------------------------------------------------
130
+ column_eras:
131
+ finding: >-
132
+ Додаток 4 prints four columns of літеросполуки under a SINGLE unlabelled
133
+ heading, "Літеросполука" (verified against the annex's own HTML: one
134
+ `colspan=4` header cell). The instrument therefore does NOT say that column
135
+ 1 is the 2004 set, column 2 the 2013 set and columns 3-4 the 2021 additions.
136
+ what_is_claimed_here: >-
137
+ Only that all four pairs in a row are, today, valid літеросполуки for that
138
+ region. That is what the instrument says and it is all this table asserts in
139
+ `annex_4_codes`.
140
+ secondary_attribution:
141
+ evidence: secondary-wikipedia
142
+ claim: >-
143
+ The Ukrainian Wikipedia article attributes column 1 to the 2004
144
+ distribution, column 2 to a 2013 amendment of ДСТУ 4278:2004 that added
145
+ the НА-НХ, ІА-ІН and КА-КХ ranges, and columns 3-4 to a 2021 addition of
146
+ two further codes per region.
147
+ corroboration: >-
148
+ Column 1 IS corroborated independently and primarily: it matches Додаток Б
149
+ of ДСТУ 4278:2004 pair for pair (АК Crimea, АВ Vinnytsia, АС Volyn, …,
150
+ СН Sevastopol). Columns 2-4 have no primary corroboration in this pass.
151
+ known_divergence: >-
152
+ For Crimea the article gives the second-era code as "КК"; the instrument's
153
+ second column is "МА", and "КК" appears in the instrument as one of Kyiv
154
+ city's four codes. Where the article and the annex disagree, THE ANNEX IS
155
+ RECORDED. This divergence is the reason the era attribution is quarantined
156
+ into this block instead of being written onto the rows.
157
+ source: "https://uk.wikipedia.org/wiki/Номерні_знаки_України # section «Коди адміністративних регіонів». secondary-wikipedia; accessed 2026-08-03"
158
+
159
+ # ---------------------------------------------------------------------------
160
+ # The region slot when it is NOT a region (Розділ III п. 1, from 12.12.2022).
161
+ # ---------------------------------------------------------------------------
162
+ online_registration_codes:
163
+ applies_to: "vehicles registered on a contract concluded in electronic form"
164
+ instrument: "Наказ МВС № 814 від 12.12.2022, amending Розділ III п. 1"
165
+ codes:
166
+ - code: "ЕD"
167
+ code_ascii: "ED"
168
+ script: "MIXED — Cyrillic Е U+0415 followed by LATIN D. Recorded as published; the instrument mixes scripts inside a single two-character token here and nowhere else"
169
+ channel: "Електронний кабінет водія (the МВС driver's e-cabinet)"
170
+ channel_evidence: secondary-wikipedia
171
+ - code: "DC"
172
+ code_ascii: "DC"
173
+ script: "Latin"
174
+ channel: "Електронний кабінет водія"
175
+ channel_evidence: secondary-wikipedia
176
+ - code: "DI"
177
+ code_ascii: "DI"
178
+ script: "Latin"
179
+ channel: "Портал «Дія»"
180
+ channel_evidence: secondary-wikipedia
181
+ - code: "PD"
182
+ code_ascii: "PD"
183
+ script: "Latin"
184
+ channel: "Портал «Дія»"
185
+ channel_evidence: secondary-wikipedia
186
+ note: >-
187
+ The instrument names the four літеросполуки and says only that they replace
188
+ the region code for electronically registered vehicles. WHICH channel maps
189
+ to WHICH pair is a Wikipedia claim, tagged per code above; the instrument
190
+ does not split them. What IS primary is that a plate carrying any of the
191
+ four encodes no geography.
192
+ source: "https://zakon.rada.gov.ua/laws/show/z0353-21 # Розділ III п. 1, as amended by Наказ МВС № 814 від 12.12.2022. Accessed 2026-08-03"
193
+
194
+ # ---------------------------------------------------------------------------
195
+ # What this table is NOT: the older systems, recorded so a consumer knows the
196
+ # limits rather than guessing at them.
197
+ # ---------------------------------------------------------------------------
198
+ superseded_systems:
199
+ - system: "2004 letters"
200
+ period: { start: 2004 }
201
+ status: "still valid — column 1 of every row below"
202
+ extra: >-
203
+ ДСТУ 4278:2004 Додаток Б also carried a 28th entry with no region:
204
+ «ІІ — Загальнодержавна» (a nationwide, region-free pair). It is NOT in
205
+ Додаток 4 of the 2021 order. Ukrainian Wikipedia reports ІІ was withdrawn
206
+ from issue in 2006 (secondary-wikipedia). Plates bearing ІІ may still
207
+ exist; this table cannot decode them to a region, and should not try.
208
+ - system: "1995-2004 numeric"
209
+ period: { start: 1995, end: 2004 }
210
+ status: "NOT MODELLED — no primary secured in this pass"
211
+ description: >-
212
+ From 1995 to 2004 the plate carried five digits and a two-letter series,
213
+ with a TWO-DIGIT region code on the band under the flag (ДСТУ 3650-97,
214
+ named as the governing standard by постанова КМУ від 11.07.2000 № 1081
215
+ п. 2). The numeric codes 01-27 of Додаток 6 descend from that system. The
216
+ LETTER series of that era were allocated regionally on a different map
217
+ from today's — Ukrainian Wikipedia records, for example, КР/КО/РК for
218
+ Crimea and КА/КВ/КЕ/КІ/КН/КТ/ІІ/ОО for Kyiv city — so a pre-2004 pair
219
+ MUST NOT be decoded against `annex_4_codes`. ДСТУ 3650-97 itself was not
220
+ reached in this pass.
221
+ evidence: secondary-wikipedia
222
+
223
+ # ---------------------------------------------------------------------------
224
+ # 27 regions. `annex_4_codes` and `annex_6_numeric` are the instrument's own;
225
+ # `annex_4_codes_ascii` is the glyph fold defined in `script:` above;
226
+ # `region` is the annex's own Ukrainian wording, verbatim.
227
+ # `region_en` and `iso_3166_2` are EDITORIAL cross-references added by this
228
+ # dataset for consumers — they are not in the instrument, and the ISO codes
229
+ # were not checked against the ISO register in this pass.
230
+ # ---------------------------------------------------------------------------
231
+ regions:
232
+ - region: "Автономна Республіка Крим"
233
+ region_en: "Autonomous Republic of Crimea"
234
+ iso_3166_2: "UA-43"
235
+ annex_4_codes: ["АК", "МА", "ТК", "МК"]
236
+ annex_4_codes_ascii: ["AK", "MA", "TK", "MK"]
237
+ annex_6_numeric: ["01"]
238
+ - region: "Вінницька область"
239
+ region_en: "Vinnytsia Oblast"
240
+ iso_3166_2: "UA-05"
241
+ annex_4_codes: ["АВ", "КВ", "ІМ", "РІ"]
242
+ annex_4_codes_ascii: ["AB", "KB", "IM", "PI"]
243
+ annex_6_numeric: ["02"]
244
+ - region: "Волинська область"
245
+ region_en: "Volyn Oblast"
246
+ iso_3166_2: "UA-07"
247
+ annex_4_codes: ["АС", "КС", "СМ", "ТС"]
248
+ annex_4_codes_ascii: ["AC", "KC", "CM", "TC"]
249
+ annex_6_numeric: ["03"]
250
+ - region: "Дніпропетровська область"
251
+ region_en: "Dnipropetrovsk Oblast"
252
+ iso_3166_2: "UA-12"
253
+ annex_4_codes: ["АЕ", "КЕ", "РР", "МІ"]
254
+ annex_4_codes_ascii: ["AE", "KE", "PP", "MI"]
255
+ annex_6_numeric: ["04"]
256
+ - region: "Донецька область"
257
+ region_en: "Donetsk Oblast"
258
+ iso_3166_2: "UA-14"
259
+ annex_4_codes: ["АН", "КН", "ТН", "МН"]
260
+ annex_4_codes_ascii: ["AH", "KH", "TH", "MH"]
261
+ annex_6_numeric: ["05"]
262
+ - region: "Житомирська область"
263
+ region_en: "Zhytomyr Oblast"
264
+ iso_3166_2: "UA-18"
265
+ annex_4_codes: ["АМ", "КМ", "ТМ", "МВ"]
266
+ annex_4_codes_ascii: ["AM", "KM", "TM", "MB"]
267
+ annex_6_numeric: ["06"]
268
+ - region: "Закарпатська область"
269
+ region_en: "Zakarpattia Oblast"
270
+ iso_3166_2: "UA-21"
271
+ annex_4_codes: ["АО", "КО", "МТ", "МО"]
272
+ annex_4_codes_ascii: ["AO", "KO", "MT", "MO"]
273
+ annex_6_numeric: ["07"]
274
+ - region: "Запорізька область"
275
+ region_en: "Zaporizhzhia Oblast"
276
+ iso_3166_2: "UA-23"
277
+ annex_4_codes: ["АР", "КР", "ТР", "МР"]
278
+ annex_4_codes_ascii: ["AP", "KP", "TP", "MP"]
279
+ annex_6_numeric: ["08"]
280
+ - region: "Івано-Франківська область"
281
+ region_en: "Ivano-Frankivsk Oblast"
282
+ iso_3166_2: "UA-26"
283
+ annex_4_codes: ["АТ", "КТ", "ТО", "ХС"]
284
+ annex_4_codes_ascii: ["AT", "KT", "TO", "XC"]
285
+ annex_6_numeric: ["09"]
286
+ - region: "Київська область"
287
+ region_en: "Kyiv Oblast"
288
+ iso_3166_2: "UA-32"
289
+ annex_4_codes: ["АІ", "КІ", "ТІ", "ЕЕ"]
290
+ annex_4_codes_ascii: ["AI", "KI", "TI", "EE"]
291
+ annex_6_numeric: ["10"]
292
+ - region: "м. Київ"
293
+ region_en: "Kyiv (city)"
294
+ iso_3166_2: "UA-30"
295
+ annex_4_codes: ["АА", "КА", "ТТ", "КК"]
296
+ annex_4_codes_ascii: ["AA", "KA", "TT", "KK"]
297
+ annex_6_numeric: ["11", "31"]
298
+ - region: "Кіровоградська область"
299
+ region_en: "Kirovohrad Oblast"
300
+ iso_3166_2: "UA-35"
301
+ annex_4_codes: ["ВА", "НА", "ХА", "ЕА"]
302
+ annex_4_codes_ascii: ["BA", "HA", "XA", "EA"]
303
+ annex_6_numeric: ["12"]
304
+ - region: "Луганська область"
305
+ region_en: "Luhansk Oblast"
306
+ iso_3166_2: "UA-09"
307
+ annex_4_codes: ["ВВ", "НВ", "ЕР", "ЕВ"]
308
+ annex_4_codes_ascii: ["BB", "HB", "EP", "EB"]
309
+ annex_6_numeric: ["13"]
310
+ - region: "Львівська область"
311
+ region_en: "Lviv Oblast"
312
+ iso_3166_2: "UA-46"
313
+ annex_4_codes: ["ВС", "НС", "СС", "ЕС"]
314
+ annex_4_codes_ascii: ["BC", "HC", "CC", "EC"]
315
+ annex_6_numeric: ["14"]
316
+ - region: "Миколаївська область"
317
+ region_en: "Mykolaiv Oblast"
318
+ iso_3166_2: "UA-48"
319
+ annex_4_codes: ["ВЕ", "НЕ", "ХЕ", "ХН"]
320
+ annex_4_codes_ascii: ["BE", "HE", "XE", "XH"]
321
+ annex_6_numeric: ["15"]
322
+ - region: "Одеська область"
323
+ region_en: "Odesa Oblast"
324
+ iso_3166_2: "UA-51"
325
+ annex_4_codes: ["ВН", "НН", "ОО", "ЕН"]
326
+ annex_4_codes_ascii: ["BH", "HH", "OO", "EH"]
327
+ annex_6_numeric: ["16"]
328
+ - region: "Полтавська область"
329
+ region_en: "Poltava Oblast"
330
+ iso_3166_2: "UA-53"
331
+ annex_4_codes: ["ВІ", "НІ", "ХІ", "ЕІ"]
332
+ annex_4_codes_ascii: ["BI", "HI", "XI", "EI"]
333
+ annex_6_numeric: ["17"]
334
+ - region: "Рівненська область"
335
+ region_en: "Rivne Oblast"
336
+ iso_3166_2: "UA-56"
337
+ annex_4_codes: ["ВК", "НК", "ХК", "ЕК"]
338
+ annex_4_codes_ascii: ["BK", "HK", "XK", "EK"]
339
+ annex_6_numeric: ["18"]
340
+ - region: "Сумська область"
341
+ region_en: "Sumy Oblast"
342
+ iso_3166_2: "UA-59"
343
+ annex_4_codes: ["ВМ", "НМ", "ХМ", "ЕМ"]
344
+ annex_4_codes_ascii: ["BM", "HM", "XM", "EM"]
345
+ annex_6_numeric: ["19"]
346
+ - region: "Тернопільська область"
347
+ region_en: "Ternopil Oblast"
348
+ iso_3166_2: "UA-61"
349
+ annex_4_codes: ["ВО", "НО", "ХО", "ЕО"]
350
+ annex_4_codes_ascii: ["BO", "HO", "XO", "EO"]
351
+ annex_6_numeric: ["20"]
352
+ - region: "Харківська область"
353
+ region_en: "Kharkiv Oblast"
354
+ iso_3166_2: "UA-63"
355
+ annex_4_codes: ["АХ", "КХ", "ХХ", "ЕХ"]
356
+ annex_4_codes_ascii: ["AX", "KX", "XX", "EX"]
357
+ annex_6_numeric: ["21"]
358
+ - region: "Херсонська область"
359
+ region_en: "Kherson Oblast"
360
+ iso_3166_2: "UA-65"
361
+ annex_4_codes: ["ВТ", "НТ", "ХТ", "ЕТ"]
362
+ annex_4_codes_ascii: ["BT", "HT", "XT", "ET"]
363
+ annex_6_numeric: ["22"]
364
+ - region: "Хмельницька область"
365
+ region_en: "Khmelnytskyi Oblast"
366
+ iso_3166_2: "UA-68"
367
+ annex_4_codes: ["ВХ", "НХ", "ОХ", "РХ"]
368
+ annex_4_codes_ascii: ["BX", "HX", "OX", "PX"]
369
+ annex_6_numeric: ["23"]
370
+ - region: "Черкаська область"
371
+ region_en: "Cherkasy Oblast"
372
+ iso_3166_2: "UA-71"
373
+ annex_4_codes: ["СА", "ІА", "ОА", "РА"]
374
+ annex_4_codes_ascii: ["CA", "IA", "OA", "PA"]
375
+ annex_6_numeric: ["24"]
376
+ - region: "Чернігівська область"
377
+ region_en: "Chernihiv Oblast"
378
+ iso_3166_2: "UA-74"
379
+ annex_4_codes: ["СВ", "ІВ", "ОВ", "РВ"]
380
+ annex_4_codes_ascii: ["CB", "IB", "OB", "PB"]
381
+ annex_6_numeric: ["25"]
382
+ - region: "Чернівецька область"
383
+ region_en: "Chernivtsi Oblast"
384
+ iso_3166_2: "UA-77"
385
+ annex_4_codes: ["СЕ", "ІЕ", "ОЕ", "РЕ"]
386
+ annex_4_codes_ascii: ["CE", "IE", "OE", "PE"]
387
+ annex_6_numeric: ["26"]
388
+ - region: "м. Севастополь"
389
+ region_en: "Sevastopol (city)"
390
+ iso_3166_2: "UA-40"
391
+ annex_4_codes: ["СН", "ІН", "ОН", "РН"]
392
+ annex_4_codes_ascii: ["CH", "IH", "OH", "PH"]
393
+ annex_6_numeric: ["27"]
@@ -0,0 +1,215 @@
1
+ # plates/_decode/za-licence-marks.yml — South African LICENCE MARKS.
2
+ #
3
+ # THE SOURCE FINDING, and it decides the whole shape of plates/za.yml: South
4
+ # Africa has TWO geographic dimensions on a plate, created by two different
5
+ # limbs of ONE regulation, and a parse API that conflates them will be wrong
6
+ # about half the country.
7
+ #
8
+ # Regulation 27 of the National Road Traffic Regulations, 2000 (GNR.225 of
9
+ # 17 March 2000, made under the National Road Traffic Act 93 of 1996),
10
+ # VERBATIM:
11
+ #
12
+ # "27. Licence mark and licence number system
13
+ # (1) The MEC of each province shall, subject to subregulation (2), by
14
+ # notice in the Provincial Gazette, determine a licence mark for the
15
+ # province concerned.
16
+ # (2) (a) The MEC of a province shall by notice in the Provincial Gazette—
17
+ # (i) allocate a licence mark to every registering authority in the
18
+ # province concerned, which licence mark shall consist of a
19
+ # combination of letters; or
20
+ # (ii) establish a licence number system for the province concerned
21
+ # which license number system shall consist of:
22
+ # (aa) a combination of three letters and three figures in any
23
+ # sequence; or
24
+ # (bb) a combination of two letters, two figures and two letters
25
+ # in any sequence:
26
+ # and the licence mark of the province concerned, referred to in sub
27
+ # regulation (1): Provided that vowels and the letter 'Q' shall not be
28
+ # used and the first letter shall not be the letter 'G'.
29
+ # (3) Every motor vehicle licensed in a province shall be allocated with a
30
+ # licence number and such licence number shall, subject to subregulation
31
+ # (5) and regulation 28, consist of the licence mark referred to in
32
+ # subregulation (2)(a)(i) and figures, or the letters and figures
33
+ # allocated from the licence number system referred to in subregulation
34
+ # (2)(a)(ii)."
35
+ #
36
+ # So the two dimensions are:
37
+ #
38
+ # PROVINCIAL MARK — reg 27(1). One per province, printed at the END of a
39
+ # licence number issued under a provincial licence NUMBER SYSTEM
40
+ # (reg 27(2)(a)(ii)). This is the "GP", "MP", "NC" suffix everyone knows.
41
+ #
42
+ # REGISTERING-AUTHORITY MARK — reg 27(2)(a)(i). One per registering
43
+ # authority (a town/city licensing office), printed at the FRONT, followed
44
+ # by figures. This is the Western Cape "CA 123-456" and the pre-2023
45
+ # KwaZulu-Natal "ND 12345" style, and it is the DIRECT DESCENDANT of the
46
+ # pre-1994 four-province town-code system: those codes were allocated by
47
+ # the old provincial administrations and survived the 1994 reorganisation
48
+ # inside the two provinces that never switched to a suffix system.
49
+ #
50
+ # The two are mutually exclusive per province — reg 27(2)(a) is an "or" — and
51
+ # a province may switch by a fresh notice under reg 27(4). KwaZulu-Natal did
52
+ # exactly that in December 2023.
53
+ #
54
+ # WHAT IS AND IS NOT PINNED HERE (read before trusting a row):
55
+ # * The reg 27 text above is PRIMARY and was read twice, in the consolidated
56
+ # regulations and again in a Government Gazette reproduction (GG 37542,
57
+ # General Notice 287 of 9 April 2014), which agree word for word.
58
+ # * The reg 27(1) determinations themselves are NINE SEPARATE PROVINCIAL
59
+ # GAZETTE NOTICES. Three of the nine marks below are pinned to a
60
+ # government publication (FS, GP, WP). The other six are NOT: they are
61
+ # carried on `secondary-wikipedia` evidence and are flagged row by row.
62
+ # No provincial gazette index with full-text search was reachable in this
63
+ # pass (SAFLII is behind Cloudflare, opengazettes.org.za's search has been
64
+ # retired, gazettes.africa exposes no query endpoint) — recorded as the
65
+ # single largest gap in the South African pass.
66
+ # * NO complete registering-authority mark table is published anywhere this
67
+ # pass could reach. The Western Cape rows below are the marks the Western
68
+ # Cape Government itself prints as worked examples on its own fee table;
69
+ # they are a floor, not a census. eNaTIS publishes a "live vehicle
70
+ # population per registering authority" series that would settle it, and
71
+ # natis.gov.za refused every request (HTTP 403). Recorded as a gap.
72
+ jurisdiction: za
73
+ topic: licence-marks
74
+ authority:
75
+ name: "MEC responsible for road traffic in each province, under reg. 27 of the National Road Traffic Regulations, 2000 (GNR.225 of 17 March 2000)"
76
+ url: "https://www.gov.za/sites/default/files/gcis_document/201409/37542gen287.pdf"
77
+ sources:
78
+ - "https://disasterlaw.ifrc.org/sites/default/files/media/disaster_law/2021-06/%20ROAD%20TRAFFIC%20REGULATIONS,%202000.pdf # National Road Traffic Regulations 2000 consolidated to GNR.359 of 2 May 2010 — reg 27(1),(2),(3),(4),(5) verbatim; accessed 2026-08-02"
79
+ - "https://www.gov.za/sites/default/files/gcis_document/201409/37542gen287.pdf # Government Gazette 37542, General Notice 287 of 9 April 2014 (Department of Transport, publication of proposed amendments FOR COMMENT) — reproduces reg 27(1)-(5) and reg 35 in identical words; accessed 2026-08-02"
80
+ - "https://www.policeroadstransport.fs.gov.za/wp-content/uploads/2012/09/Personalised-licence-number-system-for-the-Free-State-2002.pdf # Free State Provincial Notice 52 of 2002, Provincial Gazette 25 of 9 April 2002, para 2(1): personalised numbers 'followed by the letters FS' — the FS mark, primary; accessed 2026-08-02"
81
+ - "https://cmbinary.gauteng.gov.za/Media?path=transport/Documents/Documents/GP%20Application%20Form%20-%20Personalised%20Number%20Plate.pdf&Item=658&Type=Documents&Location=/transport # Gauteng Province form PRN1-GP, 'Application for special/personalised registration number for motor vehicle': the registration-number field is pre-printed with 'G P' — the GP mark, primary; accessed 2026-08-02"
82
+ - "https://www.westerncape.gov.za/mobility/service/applying-special-motor-vehicle-number-plates # Western Cape Government: 'Personalised number plates contain the letters WP (Western Province) at the end of the number plate' + the discrete-number fee table whose worked examples are the CY/CW/CG/CK/CB/CBY/CFM registering-authority marks; accessed 2026-08-02"
83
+ - "https://en.wikipedia.org/wiki/Vehicle_registration_plates_of_South_Africa # FINDING AID + the six unpinned provincial marks (EC, L, MP, NC, NW, ZN) and the Port Shepstone NPS->NSC change; every fact taken from it is tagged secondary-wikipedia below; accessed 2026-08-02"
84
+ period: { start: 2000 }
85
+ period_evidence: instrument-in-force
86
+ period_note: >-
87
+ 2000 is the year of the instrument that CREATES the licence-mark power read
88
+ here (GNR.225 of 17 March 2000), not the year the marks came into use. The
89
+ registering-authority marks are decades older — the Cape "C" family and the
90
+ Natal "N" family were allocated by the pre-1994 provincial administrations
91
+ and were carried across the 1994 reorganisation unchanged — and the
92
+ provincial marks were determined in the second half of the 1990s under the
93
+ Road Traffic Act 29 of 1989 and its provincial ordinances. None of those
94
+ earlier instruments was pinned in this pass. A decode of a physical plate is
95
+ therefore period-agnostic: these marks do not date a plate.
96
+
97
+ # ---------------------------------------------------------------------------
98
+ # 1. PROVINCIAL MARKS — reg 27(1). Printed at the END of the licence number.
99
+ # `system` records which limb of reg 27(2)(a) the province chose, because
100
+ # that, not the mark, is what determines the serial grammar.
101
+ # ---------------------------------------------------------------------------
102
+ maximal_munch: false
103
+ provincial_marks:
104
+ - code: EC
105
+ name: "Eastern Cape"
106
+ system: "reg 27(2)(a)(ii)(aa) — three letters and three figures"
107
+ evidence: secondary-wikipedia
108
+ note: "Mark not traced to its provincial gazette notice in this pass."
109
+ - code: FS
110
+ name: "Free State"
111
+ system: "reg 27(2)(a)(ii)(aa) — three letters and three figures"
112
+ evidence: authority-publication
113
+ note: >-
114
+ PRIMARY. Free State Provincial Notice 52 of 2002 para 2(1)(a)-(b)
115
+ requires a personalised number to be "followed by the letters FS", and
116
+ Provincial Notice 51 of 2002 Schedule 3 para 4 requires the retro-
117
+ reflective sheeting to carry "the Province by way of the letters 'FS'
118
+ inside a 12 mm circle interspersed throughout the sheeting".
119
+ - code: GP
120
+ name: "Gauteng"
121
+ system: >-
122
+ reg 27(2)(a)(ii)(aa) three letters and three figures; a two-letter /
123
+ two-figure / two-letter issue under reg 27(2)(a)(ii)(bb) is reported
124
+ from 2023 (secondary-wikipedia — see plates/za.yml#za-gp-standard-2l2f2l)
125
+ evidence: authority-publication
126
+ note: >-
127
+ PRIMARY. Gauteng Province form PRN1-GP pre-prints "G P" in each of the
128
+ three registration-number choice fields.
129
+ - code: L
130
+ name: "Limpopo"
131
+ system: "reg 27(2)(a)(ii)(aa) — three letters and three figures"
132
+ evidence: secondary-wikipedia
133
+ note: >-
134
+ The only ONE-LETTER provincial mark, which is why plates/za.yml writes
135
+ it with the pattern escape (\L) rather than as the letter token. The
136
+ province was named Northern Province until 2003 and the mark it used
137
+ before the rename was not established in this pass — recorded gap.
138
+ - code: MP
139
+ name: "Mpumalanga"
140
+ system: "reg 27(2)(a)(ii)(aa) — three letters and three figures"
141
+ evidence: secondary-wikipedia
142
+ note: "Mark not traced to its provincial gazette notice in this pass."
143
+ - code: NC
144
+ name: "Northern Cape"
145
+ system: "reg 27(2)(a)(ii)(aa) — three letters and three figures"
146
+ evidence: secondary-wikipedia
147
+ note: "Mark not traced to its provincial gazette notice in this pass."
148
+ - code: NW
149
+ name: "North West"
150
+ system: "reg 27(2)(a)(ii)(aa) — three letters and three figures"
151
+ evidence: secondary-wikipedia
152
+ note: "Mark not traced to its provincial gazette notice in this pass."
153
+ - code: WP
154
+ name: "Western Cape"
155
+ system: >-
156
+ reg 27(2)(a)(i) — registering-authority marks plus figures. WP is
157
+ therefore NOT a suffix on ordinary Western Cape plates: it appears only
158
+ on personalised numbers issued under reg 28.
159
+ evidence: authority-publication
160
+ note: >-
161
+ PRIMARY. Western Cape Government, verbatim: "Personalised number plates
162
+ contain the letters WP (Western Province) at the end of the number
163
+ plate." WP stands for the historic Western Province, not for the
164
+ province's own name.
165
+ - code: ZN
166
+ name: "KwaZulu-Natal"
167
+ system: >-
168
+ reg 27(2)(a)(ii)(bb) two letters, two figures and two letters, from
169
+ 1 December 2023; previously reg 27(2)(a)(i) registering-authority marks
170
+ plus figures
171
+ evidence: secondary-wikipedia
172
+ note: >-
173
+ The 1 December 2023 switch itself IS pinned to a government publication
174
+ (SAnews.gov.za, the Government Communication and Information System) —
175
+ it is the two-letter mark "ZN" that rests on Wikipedia here.
176
+
177
+ # ---------------------------------------------------------------------------
178
+ # 2. REGISTERING-AUTHORITY MARKS — reg 27(2)(a)(i). Printed at the FRONT,
179
+ # followed by figures. INCOMPLETE BY CONSTRUCTION: see the header. Every
180
+ # row here is a mark a government page prints as its own worked example.
181
+ # ---------------------------------------------------------------------------
182
+ registering_authority_marks_note: >-
183
+ This is a floor, not a census, and a consumer MUST NOT treat an unlisted
184
+ C-initial or N-initial mark as invalid. The mechanism is the sourced fact:
185
+ a Western Cape mark is two or three letters beginning with C, a pre-2023
186
+ KwaZulu-Natal mark is two or three letters beginning with N, and both are
187
+ followed by up to six figures. The full tables live in Western Cape and
188
+ KwaZulu-Natal provincial gazettes that this pass could not reach.
189
+ registering_authority_marks:
190
+ - { code: CA, province: WP, name: "Cape Town", evidence: corroboration-only, note: "The best-known South African mark; widely printed as 'CA 123-456'. Not pinned to a Western Cape gazette in this pass." }
191
+ - { code: CY, province: WP, name: "unresolved (Western Cape)", evidence: authority-publication, note: "Western Cape Government fee table, worked example 'CY 6'." }
192
+ - { code: CW, province: WP, name: "unresolved (Western Cape)", evidence: authority-publication, note: "Western Cape Government fee table, worked example 'CW 16'." }
193
+ - { code: CG, province: WP, name: "unresolved (Western Cape)", evidence: authority-publication, note: "Western Cape Government fee table, worked example 'CG 131'." }
194
+ - { code: CK, province: WP, name: "unresolved (Western Cape)", evidence: authority-publication, note: "Western Cape Government fee table, worked example 'CK 1441'." }
195
+ - { code: CB, province: WP, name: "unresolved (Western Cape)", evidence: authority-publication, note: "Western Cape Government fee table, worked example 'CB 131'." }
196
+ - { code: CBY, province: WP, name: "unresolved (Western Cape)", evidence: authority-publication, note: "Western Cape Government fee table, worked examples 'CBY 3' and 'CBY 15' — a THREE-letter registering-authority mark, which is why plates/za.yml admits 1-2 letters after the leading C." }
197
+ - { code: CFM, province: WP, name: "unresolved (Western Cape)", evidence: authority-publication, note: "Western Cape Government fee table, worked example 'CFM 2332' — three-letter mark." }
198
+ - { code: CAA, province: WP, name: "Cape Town (second series)", evidence: secondary-wikipedia, note: "Reported introduced 13 April 2019 when the CA combinations were exhausted. Not pinned to a gazette." }
199
+ - { code: CAW, province: WP, name: "George (first series)", evidence: secondary-wikipedia, note: "Reported exhausted in late 2019." }
200
+ - { code: CAG, province: WP, name: "George (second series)", evidence: secondary-wikipedia, note: "Reported introduced late 2019 when CAW was exhausted." }
201
+ - { code: NPS, province: ZN, name: "Port Shepstone (former)", evidence: secondary-wikipedia, note: "Reported replaced by NSC on 30 June 2020." }
202
+ - { code: NSC, province: ZN, name: "Port Shepstone", evidence: secondary-wikipedia, note: "Reported in use from 30 June 2020 until the province moved to the ZN system on 1 December 2023." }
203
+
204
+ # ---------------------------------------------------------------------------
205
+ # 3. NON-GEOGRAPHIC TERMINAL LETTERS — the trap this table exists to prevent.
206
+ # These look like provincial marks and are not: they are issuance classes
207
+ # under reg 27(5) and reg 71(2), and they are modelled as SERIES in
208
+ # plates/za.yml, never decoded as geography.
209
+ # ---------------------------------------------------------------------------
210
+ not_geographic:
211
+ - { token: G, meaning: "Department of State — reg 27(5)(a)(ii): 'the letter G followed by two letters, three figures, and the letter G'. Also the reason the reg 27(2) proviso forbids G as the FIRST letter of an ordinary licence number.", series: "plates/za.yml#za-government-g" }
212
+ - { token: B, meaning: "South African Police Service — reg 27(5)(b): 'three letters, three figures, followed by the letter B'.", series: "plates/za.yml#za-police-b" }
213
+ - { token: D, meaning: "Diplomatic/consular and international organisations — reg 27(5)(d): the grammar is set by the Director-General of Foreign Affairs and is not published, but the number 'shall end in the letter D'.", series: "plates/za.yml#za-diplomatic-d" }
214
+ - { token: ZK, meaning: "Set aside for the use by the King of the Zulu Nation — reg 27(5)(c), as substituted by GNR.865 of 28 September 2007: 'the letters ZK followed by figures or letters or combination of figures and letters'. A PREFIX, not a suffix.", series: "plates/za.yml#za-zulu-royal-zk" }
215
+ - { token: A, meaning: "Motor trade (dealer) number — reg 71(2)(a): 'the letter A followed by two letters, three figures and the licence mark of the province concerned'. A dealer number therefore carries a provincial mark AND a leading A.", series: "plates/za.yml#za-dealer-a" }
@@ -22,4 +22,5 @@ electric: EV-distinct plates or suffixes (German E, CN green plates)
22
22
  seasonal: validity-window plates (German Saisonkennzeichen)
23
23
  agricultural: farm vehicles/equipment where separately serialized
24
24
  personalized: owner-chosen serials inside an official frame
25
+ sport: competition/motorsport vehicles registered under their own series, distinct from specialty (an optional design on an ordinary serial) and from historic (a sports vehicle may be new) - CZ vyhlaska 343/2014 Sb. par. 26 odst. 5, SK zakon 8/2009 Z. z. par. 127 ods. 9
25
26
  specialty: optional-design programs on standard serials (US state programs)