polytypo 1.4.1 → 1.6.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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/polytypo/data/VERSION +1 -1
  3. data/lib/polytypo/data/fixtures/cs.json +1 -1
  4. data/lib/polytypo/data/fixtures/de-CH.json +1 -1
  5. data/lib/polytypo/data/fixtures/de-DE.json +1 -1
  6. data/lib/polytypo/data/fixtures/el.json +1 -1
  7. data/lib/polytypo/data/fixtures/en-GB.json +50 -1
  8. data/lib/polytypo/data/fixtures/en-US.json +41 -1
  9. data/lib/polytypo/data/fixtures/es.json +1 -1
  10. data/lib/polytypo/data/fixtures/fi.json +1 -1
  11. data/lib/polytypo/data/fixtures/fr-CA.json +1 -1
  12. data/lib/polytypo/data/fixtures/fr.json +9 -1
  13. data/lib/polytypo/data/fixtures/it.json +1 -1
  14. data/lib/polytypo/data/fixtures/locale-resolution.json +13 -1
  15. data/lib/polytypo/data/fixtures/nl.json +1 -1
  16. data/lib/polytypo/data/fixtures/pl.json +1 -1
  17. data/lib/polytypo/data/fixtures/pt-BR.json +1 -1
  18. data/lib/polytypo/data/fixtures/pt-PT.json +1 -1
  19. data/lib/polytypo/data/fixtures/ru.json +1 -1
  20. data/lib/polytypo/data/fixtures/sv.json +1 -1
  21. data/lib/polytypo/data/fixtures/tr.json +250 -0
  22. data/lib/polytypo/data/fixtures/uk.json +1 -1
  23. data/lib/polytypo/data/locales/registry.json +3 -2
  24. data/lib/polytypo/data/locales/tr.json +72 -0
  25. data/lib/polytypo/data/rules/apostrophe.md +183 -20
  26. data/lib/polytypo/data/rules/modes.md +29 -4
  27. data/lib/polytypo/data/rules/nbsp.md +20 -6
  28. data/lib/polytypo/data/rules/order.json +2 -2
  29. data/lib/polytypo/data/rules/pipeline-idempotency.md +3 -2
  30. data/lib/polytypo/data/rules/quotes.md +234 -9
  31. data/lib/polytypo/data/rules/symbols.md +25 -5
  32. data/lib/polytypo/engine/rules/apostrophe.rb +14 -1
  33. data/lib/polytypo/version.rb +1 -1
  34. metadata +3 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 666e8d6abb66f68efd99b02224e7a7a344933e5707f9cb32fc2169e615bb1d15
4
- data.tar.gz: bd1a363b0c0a29be241a7455af03699f0f4c76f37ad24c4685d64a8ccad247e8
3
+ metadata.gz: d51bb2ff87f0296fb0e541eb321c03045e3ea6ccee4ff983cccbfa39469d5714
4
+ data.tar.gz: 77cdd431d046c4e3708053a651712363e5bef21c2f9c245fd203f74c7f68917a
5
5
  SHA512:
6
- metadata.gz: 451be400df665a42f7ebf3ef9ca20a16016544d404649446c39040382570311428d2eac903a3b3042929bcd25917f4fffd79d7cf173671be5e112fb9f97d58c7
7
- data.tar.gz: 88706e664349141c734be770fbab45208ce806c2b7a6d8b37982b34d40ff7eed81fe3167cbbe7681451e50fc0487fb63ed762e53b7603c84f991cc3e883bf698
6
+ metadata.gz: 5ff10230c85bb817a99c225d36fc3525b3690017fb157c78ef208a8a5a9f94df0bfa220c633a9f02a72c8dd5b393eac1768cdc65b57ce0cfbb8524d0cd23b512
7
+ data.tar.gz: a1ddd083a482adf73af4009b3df9dea11809f21163bb95503bcc7abec611cdaa5ef1dfad40189295e28b1ee3280efe4a40b6d620a2a002c439128bd99051cac1
@@ -1 +1 @@
1
- 1.4.0
1
+ 1.6.0
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "cs",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "de-CH",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "de-DE",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "el",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "en-GB",
4
4
  "cases": [
5
5
  {
@@ -1339,6 +1339,55 @@
1339
1339
  "in": "'a'<code>x</code>'b'",
1340
1340
  "out": "‘a’<code>x</code>‘b’",
1341
1341
  "note": "The negative control, and the reason the veto reads a cited fragment rather than the marker itself. modes.md §3.3 puts the marker in OPENISH precisely so the second pair here can open flush after a span; letting the marker satisfy the medial-elision veto's ALNUM test would have broken this row and en-us-markdown-commonmark-boundary-nested-quotes with it. The run b is not a listed fragment, so the quotation stands."
1342
+ },
1343
+ {
1344
+ "id": "en-gb-apostrophe-closing-guillemets-agree",
1345
+ "rule": "apostrophe",
1346
+ "mode": "text",
1347
+ "in": "»Wort«'s, ‹Wort›'s and «Wort»'s.",
1348
+ "out": "»Wort«’s, ‹Wort›’s and «Wort»’s.",
1349
+ "note": "apostrophe.md §6 row 21 — the asymmetry case 2a removes, in one line. The first form converted before 1.5.0 because U+00AB is an OPENISH member and case 4 reads OPENISH on the left; the other two stayed straight because U+00BB and U+203A are CLOSEISH members and no left-hand test read that class. Same shape, same reading, three glyphs, now one verdict. Foreign glyphs in en-GB by design: under quotes.md §0 mandate 1 they are re-typesetting candidates, and en-GB does re-typeset them when they form a pair — «Wort» on its own becomes ‘Wort’. None of the three is paired here, and the reason is quotes' V1 same-code-point veto reading V1ID(U+0027) = U+2019 (quotes.md §5), so this case is a V1ID witness as well as a case 2a one."
1350
+ },
1351
+ {
1352
+ "id": "en-gb-markdown-commonmark-possessive-after-paren-past-code-span",
1353
+ "rule": "apostrophe",
1354
+ "mode": "markdown",
1355
+ "dialect": "commonmark",
1356
+ "in": "The `nbsp` (R₈)'s emission alphabet is one character.\n",
1357
+ "out": "The `nbsp` (R₈)’s emission alphabet is one character.\n",
1358
+ "note": "Case 2a across a mode adapter: the code span is skipped, the parenthetical is prose, and the mark's left neighbour in the processable text is the literal U+0029 rather than modes.md §3.2's marker. The marker case is case 4's and is pinned separately."
1359
+ },
1360
+ {
1361
+ "id": "en-gb-apostrophe-closeish-punctuation-declined",
1362
+ "rule": "apostrophe",
1363
+ "mode": "text",
1364
+ "in": "He said,'yes' and left.",
1365
+ "out": "He said,'yes’ and left.",
1366
+ "note": "apostrophe.md §6 row 23: U+002C is deliberately excluded from CLOSEDELIM. `quotes` declined the pairing because canOpen's right-test rejects a CLOSEISH left neighbour, and this rule cannot tell an opening quotation mark after a comma from a possessive — so the leading mark stays U+0027, recoverable per §7 item 4, and the trailing mark is case 3. The row's output is the same before and after spec 1.5.0 and is pinned so the exclusion stays deliberate."
1367
+ },
1368
+ {
1369
+ "id": "en-gb-apostrophe-prime-after-superscript-untouched",
1370
+ "rule": "apostrophe",
1371
+ "mode": "text",
1372
+ "in": "f'(x) = 2 and f²'(x) = 4.",
1373
+ "out": "f'(x) = 2 and f²'(x) = 4.",
1374
+ "note": "Both primes survive spec 1.5.0, and for a reason worth naming: case 2a rejects them on its LEFT-test, not the case 1 prime guard, which reads DIGIT on the left only. The left neighbours here are the letter f and U+00B2, general category No, and neither is in CLOSEDELIM. The right-test rejects them as well — U+0028 is in no right-hand class — so nothing any converting case accepts is present on either side."
1375
+ },
1376
+ {
1377
+ "id": "en-gb-apostrophe-possessive-after-closing-single-quote",
1378
+ "rule": "apostrophe",
1379
+ "mode": "text",
1380
+ "in": "A ‘quoted’'s meaning.",
1381
+ "out": "A ‘quoted’’s meaning.",
1382
+ "note": "U+2019 is the CLOSEDELIM member the idempotency argument turns on (apostrophe.md §5), and the one a port is most likely to leave out: it is both this rule's only emission and a member of a class the rule now reads on the left. The doubled glyph is what the ladder specifies rather than an artefact of it: the left neighbour is a closing delimiter and the right is a letter, so case 2a converts, and this rule reorders and removes nothing. Whether an editor would rather see the construction rephrased is outside its remit — it decides what the author typed, not whether they should have (§7 item 9). The case is a fixed point, which is what §5's left-hand vacuity argument predicts. The two contiguous U+2019 it leaves are §7 item 10: CMOS's own editors would set a separating space there, no rule in order.json inserts one, and this rule cannot — every edit is one code point for one."
1383
+ },
1384
+ {
1385
+ "id": "en-gb-apostrophe-opening-mark-after-closing-delimiter",
1386
+ "rule": "apostrophe",
1387
+ "mode": "text",
1388
+ "in": "(aside)'quoted' here",
1389
+ "out": "(aside)’quoted’ here",
1390
+ "note": "apostrophe.md §6 row 25 and §7 item 9 — case 2a's accepted cost, pinned so no port can narrow or widen it silently. The author meant a quotation and both marks now read as closing glyphs. It was mismatched before spec 1.5.0 too, in the other direction: 1.4.0 gave (aside)'quoted’ here, case 3 having curled the trailing mark while the leading one matched no case. `quotes` declines the leading mark because canOpen's right-test rejects a CLOSEISH left neighbour, so a quotation opening flush after a closing delimiter is exactly the shape it cannot pair, and two neighbours cannot separate that from a possessive."
1342
1391
  }
1343
1392
  ]
1344
1393
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "en-US",
4
4
  "cases": [
5
5
  {
@@ -2530,6 +2530,46 @@
2530
2530
  "in": "He said <em>'s'</em> loudly.",
2531
2531
  "out": "He said <em>’s’</em> loudly.",
2532
2532
  "note": "Accepted false positive, recorded in the suite rather than left in someone's content: a quotation inside an inline span whose content is EXACTLY a listed fragment is read as an elision. Strictly narrower than, and the same family as, the universal medial-n veto's accepted The letter 'n' is common. — it needs the span boundary as well as the single-fragment content. '<em>x</em>', '<em>no</em>' and '<em>fine</em>' in the same position are unaffected. quotes.md §3.2."
2533
+ },
2534
+ {
2535
+ "id": "en-us-apostrophe-possessive-after-closing-paren",
2536
+ "rule": "apostrophe",
2537
+ "mode": "text",
2538
+ "in": "The pipeline (order 90)'s own output is stable.",
2539
+ "out": "The pipeline (order 90)’s own output is stable.",
2540
+ "note": "apostrophe.md §6 row 19, case 2a (spec 1.5.0): U+0029 is in CLOSEDELIM, so a possessive attaching to a parenthetical converts. Through spec 1.4.0 this was case 5 — the ladder's right side accepted every CLOSEISH member but its left side accepted no closing delimiter at all."
2541
+ },
2542
+ {
2543
+ "id": "en-us-apostrophe-possessive-after-closing-quote",
2544
+ "rule": "apostrophe",
2545
+ "mode": "text",
2546
+ "in": "“Hamlet”'s first line is the question.",
2547
+ "out": "“Hamlet”’s first line is the question.",
2548
+ "note": "apostrophe.md §6 row 20, case 2a: U+201D is en-US's own primary closing glyph. `quotes` leaves both existing glyphs in place (they are already this locale's pair) and declines the U+0027, which then reaches case 2a. The case pins the mark's identity, not the construction's merit — CMOS's reachable answer on the possessive of a quoted title steers to an attributive rephrasing and endorses none of the possessive forms, which is advice about what to write rather than a claim about what the mark is (case 2a, §7 item 10)."
2549
+ },
2550
+ {
2551
+ "id": "en-us-apostrophe-possessive-after-closing-brace-and-bracket",
2552
+ "rule": "apostrophe",
2553
+ "mode": "text",
2554
+ "in": "{user}'s account and footnote [3]'s author.",
2555
+ "out": "{user}’s account and footnote [3]’s author.",
2556
+ "note": "apostrophe.md §6 row 22, case 2a for U+007D and U+005D. A template placeholder closes a group the way any bracket does; this rule has no notion of interpolation syntax and needs none."
2557
+ },
2558
+ {
2559
+ "id": "en-us-apostrophe-symbol-left-declined",
2560
+ "rule": "apostrophe",
2561
+ "mode": "text",
2562
+ "in": "10%'u 24m²'ye 50°'lik",
2563
+ "out": "10%'u 24m²'ye 50°'lik",
2564
+ "note": "apostrophe.md §6 row 24 and §7 item 8: no symbol is in CLOSEDELIM — not U+0025, not U+00B0, not a superscript digit — so every mark here is case 5 and the input is a fixed point. Pinned because issue #28 asked for exactly this widening and it was declined on evidence: TDK's own rules attest the apostrophe after abbreviations and numerals, where case 2 already converts it, and Turkish writes the percent sign before the number."
2565
+ },
2566
+ {
2567
+ "id": "en-us-apostrophe-closing-paren-deleted-by-symbols",
2568
+ "rule": "apostrophe",
2569
+ "mode": "text",
2570
+ "in": "(c)'. and (c)'s",
2571
+ "out": "©'. and ©’s",
2572
+ "note": "symbols.md §5's I₆ discharge, deletion half (spec 1.5.0): §3.2 step 6 deletes the U+0029 that case 2a reads. Both directions in one case. The first mark does not convert — its right neighbour is U+002E, not ALNUM — and after the replacement its left neighbour is the emitted sign, which is in no class, so it does not convert on a second pass either. The second mark converts here, one rule before symbols shortens the span, and is U+2019 by the time symbols runs, which its own S2 guard accepts. Through spec 1.4.0 the second mark stayed straight."
2533
2573
  }
2534
2574
  ]
2535
2575
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "es",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "fi",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "fr-CA",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "fr",
4
4
  "cases": [
5
5
  {
@@ -928,6 +928,14 @@
928
928
  "in": "Il dit <em>'l'</em> ici.",
929
929
  "out": "Il dit <em>’l’</em> ici.",
930
930
  "note": "The accepted false positive in the locale with the widest exposure to it: fr lists thirteen fragments, eight of them a single letter, so a quotation whose whole content is one of them is read as an elision here more readily than anywhere else. Same class as en-us-html-span-boundary-listed-fragment-quoted and as the universal medial-n veto's accepted The letter 'n' is common. — pinned in both locales so the exposure sits in the suite rather than in someone's content. quotes.md §3.2, §6 row S7."
931
+ },
932
+ {
933
+ "id": "fr-apostrophe-closing-guillemet-past-an-nbsp-insertion",
934
+ "rule": "apostrophe",
935
+ "mode": "text",
936
+ "in": "Le «mot»'s résumé.",
937
+ "out": "Le « mot »’s résumé.",
938
+ "note": "The one configuration where a rule running AFTER apostrophe touches a CLOSEDELIM neighbour, so nbsp.md §5's I₆ discharge has a witness rather than only prose. N1/N2 put fr's inner no-break space on the glyph's INNER side, so the U+00BB that case 2a reads stays immediately left of the mark and the verdict is identical before and after the insertion. Synthetic rather than natural French — a possessive 's is not French — and deliberately so, in the standing quotes.md §6 gives its own adversarial de-CH witness: what is being pinned is the rule interaction, not an idiom."
931
939
  }
932
940
  ]
933
941
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "it",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "cases": [
4
4
  {
5
5
  "id": "exact-en-us",
@@ -276,6 +276,18 @@
276
276
  "tag": "pt-AO",
277
277
  "resolves": "pt-PT",
278
278
  "note": "section 3.4 step 3b: the strip lands on an alias key, so the alias is followed — the one path through step 3 that steps 1 and 2 cannot reach."
279
+ },
280
+ {
281
+ "id": "exact-tr",
282
+ "tag": "tr",
283
+ "resolves": "tr",
284
+ "note": "section 3.4 step 1. Added with the locale in spec 1.6.0, for the reason exact-es records: a registry member with no resolution case is a member nothing proves resolves rather than throws."
285
+ },
286
+ {
287
+ "id": "strip-tr-tr",
288
+ "tag": "tr-TR",
289
+ "resolves": "tr",
290
+ "note": "section 3.4 step 3a, and the tag a Turkish caller actually sends. tr needs no registry alias precisely because the region strip reaches it — this case is what makes that claim testable rather than asserted."
279
291
  }
280
292
  ]
281
293
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "nl",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "pl",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "pt-BR",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "pt-PT",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "ru",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "sv",
4
4
  "cases": [
5
5
  {
@@ -0,0 +1,250 @@
1
+ {
2
+ "spec": "1.6.0",
3
+ "locale": "tr",
4
+ "cases": [
5
+ {
6
+ "id": "tr-quotes-primary-and-nested",
7
+ "rule": "quotes",
8
+ "mode": "text",
9
+ "in": "Sordu: \"Bu, 'köşedeki' dedikleri dükkân mı?\"",
10
+ "out": "Sordu: “Bu, ‘köşedeki’ dedikleri dükkân mı?”",
11
+ "note": "Birinci derece U+201C/U+201D, ikinci derece U+2018/U+2019 — TDK «Tek Tırnak İşareti» kuralının iki derecesi tek bir cümlede. Kod noktaları Türk Dili dergisinin metin katmanından okundu, kural ise TDK Yazım Kuralları sayfasından; ikisi de tr.json içindeki sources alanında."
12
+ },
13
+ {
14
+ "id": "tr-quotes-tdk-nested-example",
15
+ "rule": "quotes",
16
+ "mode": "text",
17
+ "in": "\"Atatürk henüz 'Gazi Mustafa Kemal Paşa' idi.\"",
18
+ "out": "“Atatürk henüz ‘Gazi Mustafa Kemal Paşa’ idi.”",
19
+ "note": "TDK Yazım Kılavuzu'nun tek tırnak kuralı için verdiği örneğin kendisi (Falih Rıfkı Atay), düz işaretlerle yazılıp motora verildi. Çıktı, kaynağın bastığı iç içe biçimle aynıdır."
20
+ },
21
+ {
22
+ "id": "tr-quotes-not-guillemets",
23
+ "rule": "quotes",
24
+ "mode": "text",
25
+ "in": "«Tanrı, Musa'ya söz söylemiştir.»",
26
+ "out": "“Tanrı, Musa’ya söz söylemiştir.”",
27
+ "note": "Issue #51'de bildirilen «…» biçimi Türkçenin normu DEĞİLDİR: Türk Dili, «Tırnak İşareti Üzerine», s. 32 onu «bazı yazarlar»ın tercihi olarak tanıtır. quotes.md §0 mandate 1 uyarınca var olan her tırnak yeniden dizilebilir, bu yüzden yan tırnak TDK'nin üstten çift tırnağına çevrilir. Bu satır, hangi biçimin kazandığını sabitler."
28
+ },
29
+ {
30
+ "id": "tr-quotes-already-correct",
31
+ "rule": "quotes",
32
+ "mode": "text",
33
+ "in": "“Kendi Gök Kubbemiz” adı altında çıktı.",
34
+ "out": "“Kendi Gök Kubbemiz” adı altında çıktı.",
35
+ "note": "Doğru dizilmiş metin sabit noktadır: locale'in kendi çifti yeniden yazılmaz."
36
+ },
37
+ {
38
+ "id": "tr-apostrophe-suffix-after-abbreviation-and-numeral",
39
+ "rule": "apostrophe",
40
+ "mode": "text",
41
+ "in": "TBMM'nin kararı 1985'te açıklandı.",
42
+ "out": "TBMM’nin kararı 1985’te açıklandı.",
43
+ "note": "TDK «Kesme İşareti» 3 ve 4: kısaltmalara ve sayılara getirilen ekler kesme işaretiyle ayrılır. Her iki işaretin de iki yanı ALNUM olduğundan apostrophe.md §3.3 case 2 çalışır — bu satır locale verisi okumaz, yapısal olarak doğrudur, ve Türkçenin en sık biçimini sabitler."
44
+ },
45
+ {
46
+ "id": "tr-apostrophe-suffix-after-proper-noun",
47
+ "rule": "apostrophe",
48
+ "mode": "text",
49
+ "in": "Türkiye'nin ve Atatürk'ün",
50
+ "out": "Türkiye’nin ve Atatürk’ün",
51
+ "note": "Aynı kural, özel adlarda. «Atatürk'ün» parçası «ün» ile başlar; apostrophe kuralı hiçbir locale verisi okumadığı için bu, harf katlamasından bağımsız olarak çalışır."
52
+ },
53
+ {
54
+ "id": "tr-apostrophe-suffix-across-span-boundary",
55
+ "rule": "apostrophe",
56
+ "mode": "html",
57
+ "in": "<b>TBMM</b>'nin kararı",
58
+ "out": "<b>TBMM</b>’nin kararı",
59
+ "note": "Ek, satır içi bir span sınırına dayandığında: modes.md §3.2'nin işaretçisi apostrophe.md §3.1'in OPENISH kümesindedir, dolayısıyla işaret case 4'e düşer ve aynı U+2019'u verir. Burada eşleşecek ikinci bir tırnak olmadığı için quotes zaten bir şey yapamaz; çevreleyen bir alıntının olduğu biçim ayrı bir satırda sabitlenmiştir."
60
+ },
61
+ {
62
+ "id": "tr-ellipsis-abbreviated-after-question",
63
+ "rule": "ellipsis",
64
+ "mode": "text",
65
+ "in": "Nasıl da akşam oldu?...",
66
+ "out": "Nasıl da akşam oldu?..",
67
+ "note": "ellipsis.abbreviatedAfterTerminal = true. TDK «Üç Nokta» UYARI'sı soru ve ünlem işaretinden sonra iki noktayı yeterli sayar ve bütün örnekleri iki noktalıdır; §3 adım 4→6 üç noktayı o biçime normalleştirir. Değerin neden true olduğu ölçümle gerekçelendirilmiştir: false olsaydı «?..» girdisi «?…» olurdu, yani Kılavuz'un bastığı biçim bozulurdu."
68
+ },
69
+ {
70
+ "id": "tr-ellipsis-abbreviated-is-a-fixed-point",
71
+ "rule": "ellipsis",
72
+ "mode": "text",
73
+ "in": "Gök ekini biçer gibi!.. Başaklar daha dolmadan.",
74
+ "out": "Gök ekini biçer gibi!.. Başaklar daha dolmadan.",
75
+ "note": "TDK'nin kendi örneği (Tarık Buğra), olduğu gibi. Doğru biçim yeniden işlemeye dayanır — abbreviatedAfterTerminal = true olan bir locale'de iki nokta çıktının kendisidir, girdi hatası değil."
76
+ },
77
+ {
78
+ "id": "tr-ellipsis-plain-run",
79
+ "rule": "ellipsis",
80
+ "mode": "text",
81
+ "in": "Bekledik ... ve gitti.",
82
+ "out": "Bekledik … ve gitti.",
83
+ "note": "Terminal işaret olmadan üç nokta tek U+2026 olur; abbreviatedAfterTerminal yalnızca soru ve ünlemden SONRA devreye girer (§3 adım 6'nın TERMINAL testi)."
84
+ },
85
+ {
86
+ "id": "tr-dashes-parenthetical-none-is-a-total-noop",
87
+ "rule": "dashes",
88
+ "mode": "text",
89
+ "in": "Küçük bir sürü -dört inekle birkaç koyun- köye girdi.",
90
+ "out": "Küçük bir sürü -dört inekle birkaç koyun- köye girdi.",
91
+ "note": "dash.parenthetical = «none»: TDK ara sözü KISA ÇİZGİ ile ve bitişik yazar, locale.schema.json'ın enum'u ise yalnızca em/en uzunluklarını tanır, dolayısıyla bu gelenek ifade edilemez ve kural sessiz bırakılmıştır. Örnek TDK'nin kendisinindir ve olduğu gibi kalır. tr, dashes kuralının kanıtlanabilir biçimde total no-op olduğu üçüncü locale'dir, el ve es'ten sonra (dashes.md §6)."
92
+ },
93
+ {
94
+ "id": "tr-dashes-existing-em-dash-untouched",
95
+ "rule": "dashes",
96
+ "mode": "text",
97
+ "in": "Plan — eğer varsa — başarısız.",
98
+ "out": "Plan — eğer varsa — başarısız.",
99
+ "note": "Aynı «none» değeri, var olan bir tam kare çizgiye de dokunmaz: kuralın hiçbir emisyonu yoktur, bu yüzden yeniden dizme de yapmaz. Bu satır, «none»'ın «kısa çizgiye çevir» anlamına GELMEDİĞİNİ sabitler."
100
+ },
101
+ {
102
+ "id": "tr-ranges-none-even-when-the-rule-is-enabled",
103
+ "rule": "ranges",
104
+ "mode": "text",
105
+ "rules": {
106
+ "ranges": true
107
+ },
108
+ "in": "1914-1918 Birinci Dünya Savaşı",
109
+ "out": "1914-1918 Birinci Dünya Savaşı",
110
+ "note": "ranges.md §2: dash.range = «none» olduğunda kural hiçbir şey yayamaz. Girdi TDK «Kısa Çizgi» 7'nin kendi örneğidir — aralık normludur ama işaret kısa çizgidir, yani doğrulanmış bir en/em geleneği yoktur. Kural varsayılan olarak kapalı olduğundan bu satır onu açıkça açar; açıkken de çıktı değişmez, ki asıl sabitlenen budur."
111
+ },
112
+ {
113
+ "id": "tr-nbsp-before-units",
114
+ "rule": "nbsp",
115
+ "mode": "text",
116
+ "in": "15 °C, 20 kg ve 5 cm² ölçüldü.",
117
+ "out": "15 °C, 20 kg ve 5 cm² ölçüldü.",
118
+ "note": "N5, TDK SSS'nin «15 °C» ve «20 kg» örnekleriyle. «cm²» girişinin «cm» ile birlikte listelenmesi güvenlidir: aynı konumda en uzun eşleşme kazanır (nbsp.md §3.7)."
119
+ },
120
+ {
121
+ "id": "tr-nbsp-ton-and-mm",
122
+ "rule": "nbsp",
123
+ "mode": "text",
124
+ "in": "350 ton yük ve 12 mm kalınlık.",
125
+ "out": "350 ton yük ve 12 mm kalınlık.",
126
+ "note": "«ton» uluslararası bir simge değil bir kelimedir ve yalnızca TDK SSS'nin düzyazı örneğinden gelir; listede tutulmasının nedeni sağ sınır testinin onu «tonluk» içinde eşleştirmemesidir. Kaynak rütbesi tr.json'da açıkça yazılıdır."
127
+ },
128
+ {
129
+ "id": "tr-nbsp-percent-is-not-bound",
130
+ "rule": "nbsp",
131
+ "mode": "text",
132
+ "in": "%25 ve ‰50 oranları.",
133
+ "out": "%25 ve ‰50 oranları.",
134
+ "note": "TDK «Sayıların Yazılışı»: yüzde ve binde işaretleri sayıdan ÖNCE ve bitişik yazılır. beforeUnits ve afterSymbols'in ikisi de bu işaret için boştur ve N5/N6 yalnızca var olan bir boşluğu dönüştürür, asla eklemez — bu yüzden biçim olduğu gibi kalır. pl.json'un «%» girişinin tersi, bilerek."
135
+ },
136
+ {
137
+ "id": "tr-nbsp-abbreviation-internal-space",
138
+ "rule": "nbsp",
139
+ "mode": "text",
140
+ "in": "Kur. Bşk. ve Nö. Sb. geldi.",
141
+ "out": "Kur. Bşk. ve Nö. Sb. geldi.",
142
+ "note": "N4, TDK Kısaltmalar Dizini'nden harfi harfine alınan iki giriş. Ölçüt: her iki parçası da noktalı kısaltma olan girişler; akronim içeren biçimler dışarıda bırakıldı."
143
+ },
144
+ {
145
+ "id": "tr-nbsp-short-word-inert",
146
+ "rule": "nbsp",
147
+ "mode": "text",
148
+ "in": "ve bir de o geldi",
149
+ "out": "ve bir de o geldi",
150
+ "note": "afterShortWords boş, ve bu satır onu kanıtlanabilir yapar: Türkçede tek harfli bağlaç veya edat yoktur ve TDK asılı kalan kısa sözcükler için bir kural vermez. ru ve pl'nin listeleri buraya taşınmamıştır."
151
+ },
152
+ {
153
+ "id": "tr-hyphen-noop",
154
+ "rule": "hyphen",
155
+ "mode": "text",
156
+ "in": "Ural-Altay dil grubu ve Türk-Alman ilişkileri",
157
+ "out": "Ural-Altay dil grubu ve Türk-Alman ilişkileri",
158
+ "note": "Üç liste de boş: TDK satır sonunda bölmeyi normlar, yasaklamaz, dolayısıyla hiçbir biçim U+2011 talep etmez. Girdi TDK «Kısa Çizgi» 7'nin kendi örneğidir ve kural onun için kanıtlanabilir bir no-op'tur (hyphen.md §2)."
159
+ },
160
+ {
161
+ "id": "tr-symbols-and-spaces",
162
+ "rule": "symbols",
163
+ "mode": "text",
164
+ "in": "Copyright (c) 2026, baskı 40x60 cm.",
165
+ "out": "Copyright © 2026, baskı 40×60 cm.",
166
+ "note": "Locale'den bağımsız kurallar Türkçe metinde de çalışır: (c) → U+00A9, x → U+00D7, ve «60 cm» beforeUnits üzerinden bağlanır."
167
+ },
168
+ {
169
+ "id": "tr-spaces-punctuation-is-closed-up",
170
+ "rule": "spaces",
171
+ "mode": "text",
172
+ "in": "Nasıl gidiyorsun ? İyiyim , sağ ol .",
173
+ "out": "Nasıl gidiyorsun? İyiyim, sağ ol.",
174
+ "note": "TDK «Noktalama İşaretleri (Açıklamalar)» giriş hükmü: işaretler ait oldukları kelimelere bitişik yazılır ve boşluk işaretten SONRA gelir. spaces kuralı bunu tam olarak uygular — işaretten önceki boşluk silinir, ikili boşluk teke iner — ve nbsp.beforePunctuation'ın bu locale'de boş olmasının nedeni de aynı hükümdür: Fransızca «mot !» geleneği Türkçede yoktur, dolayısıyla silinen boşluğun geri konması istenmez."
175
+ },
176
+ {
177
+ "id": "tr-html-span-boundary-suffix-declined",
178
+ "rule": "quotes",
179
+ "mode": "html",
180
+ "in": "Dedi: '<b>TBMM</b>'nin kararı doğru.' Bitti.",
181
+ "out": "Dedi: “<b>TBMM</b>’nin kararı doğru.” Bitti.",
182
+ "note": "quotes.md §3.2'nin span-boundary elizyon vetosu (spec 1.4.0), Türkçe için canlı: ek kesme işaretiyle bir satır içi span sınırına dayanır, modes.md §3.2'nin işaretçisi «M» harfinin yerini tutar ve medial-elizyon vetosu çalışamaz. quotes.elisionClitics.after'daki «nin» girişi işareti reddeder, apostrophe (order 50) onu case 4 ile U+2019 yapar, ve yazarın kendi çifti birincil glifleri korur. Liste boş olsaydı — spec 1.6.0'dan önce her locale için olduğu gibi — ek alıntıyı açar, açılış işareti düz U+0027 kalır ve kapanış işareti kapanış glifi olurdu; ölçülmüştür (canonical issue #53). Türkçede bu biçim nadir değil, dilbilgisel olarak zorunludur."
183
+ },
184
+ {
185
+ "id": "tr-markdown-commonmark-span-boundary-suffix-declined",
186
+ "rule": "quotes",
187
+ "mode": "markdown",
188
+ "dialect": "commonmark",
189
+ "in": "Dedi: '**Ankara**'da olacak.' Bitti.\n",
190
+ "out": "Dedi: “**Ankara**’da olacak.” Bitti.\n",
191
+ "note": "Aynı mekanizma markdown'da ve «da» girişiyle: veto işaretçiyi okur, onu üreten span türünü değil. Yer adlarına gelen bulunma eki, Türkçe metinde en sık rastlanan biçimlerden biridir."
192
+ },
193
+ {
194
+ "id": "tr-html-span-boundary-listed-fragment-quoted",
195
+ "rule": "quotes",
196
+ "mode": "html",
197
+ "in": "Ek <em>'de'</em> biçiminde yazılır.",
198
+ "out": "Ek <em>’de’</em> biçiminde yazılır.",
199
+ "note": "Kabul edilen yanlış pozitif, birinin metninde bırakılmak yerine suite'e yazılmıştır: içeriği TAMAMEN listelenmiş bir parça olan ve satır içi bir span sınırına dayanan bir alıntı, ek sanılır. Bu, spec 1.4.0'ın İngilizce «s» için kabul ettiği bedelin aynısıdır ve Türkçede riski daha yüksektir, çünkü «de» ayrıca ayrı yazılan bir bağlaçtır. İki hafifletici tr.json'da kayıtlıdır: TDK'nin kendi anma biçimi başta kısa çizgi taşır ve kısa çizgi LETTER olmadığı için veto çalışamaz, ayrıca TDK bağlacı tırnaksız yazar."
200
+ },
201
+ {
202
+ "id": "tr-html-span-boundary-uppercase-suffix-not-matched",
203
+ "rule": "quotes",
204
+ "mode": "html",
205
+ "in": "Dedi: '<b>TBMM</b>'NİN kararı.' Bitti.",
206
+ "out": "Dedi: '<b>TBMM</b>“NİN kararı.” Bitti.",
207
+ "note": "Kapsam sınırı, adıyla sabitlenmiştir: büyük harfli ek eşleşmez, çünkü katlama yalnızca ilk kod noktasını ve yalnızca ASCII A-Z'yi kapsar — «N»→«n» katlanır ama kuyrukta U+0130 «İ» ile U+0069 «i» ayrı kod noktalarıdır. Katlamayı genişletmek ARCHITECTURE.md §4.4'ün noktasız ı (U+0131) yüzünden açıkça yasakladığı yerdir, dolayısıyla bu kayıp giderilmez, kabul edilir ve görünür tutulur."
208
+ },
209
+ {
210
+ "id": "tr-html-span-boundary-unlisted-suffix-not-matched",
211
+ "rule": "quotes",
212
+ "mode": "html",
213
+ "in": "Dedi: '<b>Irak</b>'ta olacak.' Bitti.",
214
+ "out": "Dedi: '<b>Irak</b>“ta olacak.” Bitti.",
215
+ "note": "İkinci kapsam sınırı: «ta» parçası, TDK'nin okunan sayfalarında kesme işaretinden sonraki dizinin TAMAMI olarak basılmadığı için listeye girmemiştir — ölçüt paradigma değil, basılı örnektir (tr.json). Liste yalnızca reddeder, dolayısıyla eksik bir giriş yanlış bir giriş değildir; bu satır hangi biçimlerin henüz onarılmadığını görünür kılar."
216
+ },
217
+ {
218
+ "id": "tr-html-span-boundary-quotation-outside-the-span",
219
+ "rule": "quotes",
220
+ "mode": "html",
221
+ "in": "Bağlaç olan '<em>de</em>' ayrı yazılır.",
222
+ "out": "Bağlaç olan “<em>de</em>” ayrı yazılır.",
223
+ "note": "Yanlış pozitifin negatif kontrolü, ve maliyetin NE KADAR DAR olduğunu gösterir. Alıntı işaretleri span'in DIŞINDA olduğunda hiçbir işaret span sınırına dayanmaz, veto hiç çalışmaz ve cümle doğru dizilir. Terimi vurgulayıp alıntılamanın olağan yazılışı budur; veto ancak yazar işaretleri span'in İÇİNE koyduğunda yanılır."
224
+ },
225
+ {
226
+ "id": "tr-html-span-boundary-tdk-hyphen-citation-form",
227
+ "rule": "quotes",
228
+ "mode": "html",
229
+ "in": "<em>'-de'</em> eki bitişik yazılır.",
230
+ "out": "<em>“-de”</em> eki bitişik yazılır.",
231
+ "note": "TDK'nin ekleri anma biçiminin kendisi, baştaki kısa çizgiyle («-da / -de / -ta / -te»). Kısa çizgi LETTER olmadığı için işaretin sağındaki dizi boş kalır, hiçbir giriş eşleşemez ve alıntı bozulmadan dizilir. Yanlış pozitifin iki ölçülen hafifleticisinden biri, prozada iddia olarak değil suite'te satır olarak."
232
+ },
233
+ {
234
+ "id": "tr-html-span-boundary-non-ascii-initial-fragment",
235
+ "rule": "quotes",
236
+ "mode": "html",
237
+ "in": "Dedi: '<b>Atatürk</b>'üm dedi.' Bitti.",
238
+ "out": "Dedi: “<b>Atatürk</b>’üm dedi.” Bitti.",
239
+ "note": "Baş harfi ASCII olmayan bir parça — «üm», U+00FC ile başlar. Eşleşir, çünkü kesme işaretinden sonraki dizi zaten küçük harflidir ve TAM karşılaştırılır; katlama yalnızca büyük harfli bir dizi için gerekir ve yalnızca ASCII A-Z'yi kapsar. Bu satır, ARCHITECTURE.md §4.4'ün yasağının bu alanı KISITLAMADIĞINI sabitler: küçük harfli Türkçe parçalar hiçbir katlamaya ihtiyaç duymaz, kayıp yalnızca büyük harfte gerçekleşir (ayrı satır)."
240
+ },
241
+ {
242
+ "id": "tr-html-span-boundary-ordinal-fragment",
243
+ "rule": "quotes",
244
+ "mode": "html",
245
+ "in": "Dedi: '<b>2</b>'nci kat.' Bitti.",
246
+ "out": "Dedi: “<b>2</b>’nci kat.” Bitti.",
247
+ "note": "Sayılara gelen sıra eki, TDK «Kesme İşareti» 4'ün kendi örneğinden («2'nci kat»). Aynı maddeden gelen «7,65'lik» ve «Atatürk'üm» de listededir; üçü de basılı örnekte kesme işaretinden sonraki dizinin TAMAMI olduğu ve çıplak bir sözcükle çakışmadığı için alınmıştır."
248
+ }
249
+ ]
250
+ }
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "locale": "uk",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.4.0",
2
+ "spec": "1.6.0",
3
3
  "$comment": "Locale resolution input. Algorithm is specified in spec/rules/locale-resolution.md and is identical in every runtime — never delegate it to a platform locale-negotiation library. \"spec\" here must track spec/VERSION exactly — it is not itself the global version source; scripts/validate-spec.mjs enforces the match.",
4
4
  "locales": [
5
5
  "en-US",
@@ -19,7 +19,8 @@
19
19
  "nl",
20
20
  "pl",
21
21
  "uk",
22
- "cs"
22
+ "cs",
23
+ "tr"
23
24
  ],
24
25
  "aliases": {
25
26
  "en": "en-US",