From 1155f0cd57fc341c0d52f00f9791115cbf8b5493 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Feb 2026 06:58:08 +0000 Subject: [PATCH 01/28] Initial plan From 74eb2ee52e99304103361edad2504c3b241add0c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Feb 2026 07:00:05 +0000 Subject: [PATCH 02/28] =?UTF-8?q?Hide=20=E2=8C=98K=20keyboard=20shortcut?= =?UTF-8?q?=20on=20mobile=20screens?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: brunoborges <129743+brunoborges@users.noreply.github.com> --- site/styles.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/site/styles.css b/site/styles.css index 430e6c3..d2e7182 100644 --- a/site/styles.css +++ b/site/styles.css @@ -1458,6 +1458,10 @@ footer a:hover { .newsletter-form { flex-direction: column; } + + .cmd-bar kbd { + display: none; + } } /* ---------- Responsive: ≤ 500px ---------- */ From 5c2108f45b9d942a7f2d5b1d32cd04b5c6d02517 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Feb 2026 20:59:16 +0000 Subject: [PATCH 03/28] Initial plan From 04a3e82dd9889b4e133a95b2c2714139e4b3d353 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Feb 2026 21:30:13 +0000 Subject: [PATCH 04/28] Add Italian (it) translations for all 112 patterns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add 'it=🇮🇹 Italiano' to html-generators/locales.properties - Create translations/strings/it.yaml with full UI string translations - Create translations/content/it/ with 112 content translation files covering all categories: language, collections, strings, streams, concurrency, io, errors, datetime, security, tooling, enterprise Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- html-generators/locales.properties | 1 + .../it/collections/collectors-teeing.yaml | 18 ++++ .../copying-collections-immutably.yaml | 18 ++++ .../collections/immutable-list-creation.yaml | 18 ++++ .../collections/immutable-map-creation.yaml | 18 ++++ .../collections/immutable-set-creation.yaml | 18 ++++ .../it/collections/map-entry-factory.yaml | 18 ++++ .../collections/reverse-list-iteration.yaml | 18 ++++ .../it/collections/sequenced-collections.yaml | 18 ++++ .../it/collections/stream-toarray-typed.yaml | 18 ++++ .../collections/unmodifiable-collectors.yaml | 18 ++++ .../completablefuture-chaining.yaml | 18 ++++ .../concurrency/concurrent-http-virtual.yaml | 18 ++++ .../executor-try-with-resources.yaml | 18 ++++ .../it/concurrency/lock-free-lazy-init.yaml | 18 ++++ .../content/it/concurrency/process-api.yaml | 18 ++++ .../content/it/concurrency/scoped-values.yaml | 18 ++++ .../content/it/concurrency/stable-values.yaml | 18 ++++ .../concurrency/structured-concurrency.yaml | 18 ++++ .../it/concurrency/thread-sleep-duration.yaml | 18 ++++ .../it/concurrency/virtual-threads.yaml | 18 ++++ .../content/it/datetime/date-formatting.yaml | 18 ++++ .../it/datetime/duration-and-period.yaml | 18 ++++ .../content/it/datetime/hex-format.yaml | 18 ++++ .../it/datetime/instant-precision.yaml | 18 ++++ .../content/it/datetime/java-time-basics.yaml | 18 ++++ .../content/it/datetime/math-clamp.yaml | 18 ++++ .../ejb-timer-vs-jakarta-scheduler.yaml | 18 ++++ .../content/it/enterprise/ejb-vs-cdi.yaml | 18 ++++ .../jdbc-resultset-vs-jpa-criteria.yaml | 18 ++++ .../content/it/enterprise/jdbc-vs-jooq.yaml | 18 ++++ .../content/it/enterprise/jdbc-vs-jpa.yaml | 18 ++++ .../jndi-lookup-vs-cdi-injection.yaml | 18 ++++ .../it/enterprise/jpa-vs-jakarta-data.yaml | 18 ++++ .../jsf-managed-bean-vs-cdi-named.yaml | 18 ++++ .../manual-transaction-vs-declarative.yaml | 18 ++++ .../enterprise/mdb-vs-reactive-messaging.yaml | 18 ++++ .../it/enterprise/servlet-vs-jaxrs.yaml | 18 ++++ ...ngleton-ejb-vs-cdi-application-scoped.yaml | 18 ++++ .../it/enterprise/soap-vs-jakarta-rest.yaml | 18 ++++ .../it/enterprise/spring-api-versioning.yaml | 18 ++++ .../spring-null-safety-jspecify.yaml | 18 ++++ .../spring-xml-config-vs-annotations.yaml | 18 ++++ .../content/it/errors/helpful-npe.yaml | 18 ++++ .../content/it/errors/multi-catch.yaml | 18 ++++ .../content/it/errors/null-in-switch.yaml | 18 ++++ .../content/it/errors/optional-chaining.yaml | 18 ++++ .../it/errors/optional-orelsethrow.yaml | 18 ++++ .../it/errors/record-based-errors.yaml | 18 ++++ .../it/errors/require-nonnull-else.yaml | 18 ++++ .../it/io/deserialization-filters.yaml | 18 ++++ .../content/it/io/file-memory-mapping.yaml | 18 ++++ .../content/it/io/files-mismatch.yaml | 18 ++++ translations/content/it/io/http-client.yaml | 18 ++++ .../content/it/io/inputstream-transferto.yaml | 18 ++++ .../content/it/io/io-class-console-io.yaml | 18 ++++ translations/content/it/io/path-of.yaml | 18 ++++ translations/content/it/io/reading-files.yaml | 18 ++++ .../try-with-resources-effectively-final.yaml | 18 ++++ translations/content/it/io/writing-files.yaml | 18 ++++ .../compact-canonical-constructor.yaml | 18 ++++ .../it/language/compact-source-files.yaml | 18 ++++ .../language/default-interface-methods.yaml | 18 ++++ .../content/it/language/diamond-operator.yaml | 18 ++++ .../it/language/exhaustive-switch.yaml | 18 ++++ .../language/flexible-constructor-bodies.yaml | 18 ++++ .../content/it/language/guarded-patterns.yaml | 18 ++++ .../language/markdown-javadoc-comments.yaml | 18 ++++ .../language/module-import-declarations.yaml | 18 ++++ .../language/pattern-matching-instanceof.yaml | 18 ++++ .../it/language/pattern-matching-switch.yaml | 18 ++++ .../language/primitive-types-in-patterns.yaml | 18 ++++ .../language/private-interface-methods.yaml | 18 ++++ .../content/it/language/record-patterns.yaml | 18 ++++ .../it/language/records-for-data-classes.yaml | 18 ++++ .../content/it/language/sealed-classes.yaml | 18 ++++ .../static-members-in-inner-classes.yaml | 18 ++++ .../static-methods-in-interfaces.yaml | 18 ++++ .../it/language/switch-expressions.yaml | 18 ++++ .../text-blocks-for-multiline-strings.yaml | 18 ++++ .../it/language/type-inference-with-var.yaml | 18 ++++ .../it/language/unnamed-variables.yaml | 18 ++++ .../it/security/key-derivation-functions.yaml | 18 ++++ .../content/it/security/pem-encoding.yaml | 18 ++++ .../content/it/security/random-generator.yaml | 18 ++++ .../content/it/security/strong-random.yaml | 18 ++++ .../content/it/security/tls-default.yaml | 18 ++++ .../it/streams/collectors-flatmapping.yaml | 18 ++++ .../it/streams/optional-ifpresentorelse.yaml | 18 ++++ .../content/it/streams/optional-or.yaml | 18 ++++ .../content/it/streams/predicate-not.yaml | 18 ++++ .../content/it/streams/stream-gatherers.yaml | 18 ++++ .../it/streams/stream-iterate-predicate.yaml | 18 ++++ .../content/it/streams/stream-mapmulti.yaml | 18 ++++ .../it/streams/stream-of-nullable.yaml | 18 ++++ .../streams/stream-takewhile-dropwhile.yaml | 18 ++++ .../content/it/streams/stream-tolist.yaml | 18 ++++ .../it/streams/virtual-thread-executor.yaml | 18 ++++ .../it/strings/string-chars-stream.yaml | 18 ++++ .../content/it/strings/string-formatted.yaml | 18 ++++ .../it/strings/string-indent-transform.yaml | 18 ++++ .../content/it/strings/string-isblank.yaml | 18 ++++ .../content/it/strings/string-lines.yaml | 18 ++++ .../content/it/strings/string-repeat.yaml | 18 ++++ .../content/it/strings/string-strip.yaml | 18 ++++ .../it/tooling/aot-class-preloading.yaml | 18 ++++ .../it/tooling/built-in-http-server.yaml | 18 ++++ .../it/tooling/compact-object-headers.yaml | 18 ++++ .../content/it/tooling/jfr-profiling.yaml | 18 ++++ .../it/tooling/jshell-prototyping.yaml | 18 ++++ .../it/tooling/junit6-with-jspecify.yaml | 18 ++++ .../content/it/tooling/multi-file-source.yaml | 18 ++++ .../it/tooling/single-file-execution.yaml | 18 ++++ translations/strings/it.yaml | 90 +++++++++++++++++++ 114 files changed, 2107 insertions(+) create mode 100644 translations/content/it/collections/collectors-teeing.yaml create mode 100644 translations/content/it/collections/copying-collections-immutably.yaml create mode 100644 translations/content/it/collections/immutable-list-creation.yaml create mode 100644 translations/content/it/collections/immutable-map-creation.yaml create mode 100644 translations/content/it/collections/immutable-set-creation.yaml create mode 100644 translations/content/it/collections/map-entry-factory.yaml create mode 100644 translations/content/it/collections/reverse-list-iteration.yaml create mode 100644 translations/content/it/collections/sequenced-collections.yaml create mode 100644 translations/content/it/collections/stream-toarray-typed.yaml create mode 100644 translations/content/it/collections/unmodifiable-collectors.yaml create mode 100644 translations/content/it/concurrency/completablefuture-chaining.yaml create mode 100644 translations/content/it/concurrency/concurrent-http-virtual.yaml create mode 100644 translations/content/it/concurrency/executor-try-with-resources.yaml create mode 100644 translations/content/it/concurrency/lock-free-lazy-init.yaml create mode 100644 translations/content/it/concurrency/process-api.yaml create mode 100644 translations/content/it/concurrency/scoped-values.yaml create mode 100644 translations/content/it/concurrency/stable-values.yaml create mode 100644 translations/content/it/concurrency/structured-concurrency.yaml create mode 100644 translations/content/it/concurrency/thread-sleep-duration.yaml create mode 100644 translations/content/it/concurrency/virtual-threads.yaml create mode 100644 translations/content/it/datetime/date-formatting.yaml create mode 100644 translations/content/it/datetime/duration-and-period.yaml create mode 100644 translations/content/it/datetime/hex-format.yaml create mode 100644 translations/content/it/datetime/instant-precision.yaml create mode 100644 translations/content/it/datetime/java-time-basics.yaml create mode 100644 translations/content/it/datetime/math-clamp.yaml create mode 100644 translations/content/it/enterprise/ejb-timer-vs-jakarta-scheduler.yaml create mode 100644 translations/content/it/enterprise/ejb-vs-cdi.yaml create mode 100644 translations/content/it/enterprise/jdbc-resultset-vs-jpa-criteria.yaml create mode 100644 translations/content/it/enterprise/jdbc-vs-jooq.yaml create mode 100644 translations/content/it/enterprise/jdbc-vs-jpa.yaml create mode 100644 translations/content/it/enterprise/jndi-lookup-vs-cdi-injection.yaml create mode 100644 translations/content/it/enterprise/jpa-vs-jakarta-data.yaml create mode 100644 translations/content/it/enterprise/jsf-managed-bean-vs-cdi-named.yaml create mode 100644 translations/content/it/enterprise/manual-transaction-vs-declarative.yaml create mode 100644 translations/content/it/enterprise/mdb-vs-reactive-messaging.yaml create mode 100644 translations/content/it/enterprise/servlet-vs-jaxrs.yaml create mode 100644 translations/content/it/enterprise/singleton-ejb-vs-cdi-application-scoped.yaml create mode 100644 translations/content/it/enterprise/soap-vs-jakarta-rest.yaml create mode 100644 translations/content/it/enterprise/spring-api-versioning.yaml create mode 100644 translations/content/it/enterprise/spring-null-safety-jspecify.yaml create mode 100644 translations/content/it/enterprise/spring-xml-config-vs-annotations.yaml create mode 100644 translations/content/it/errors/helpful-npe.yaml create mode 100644 translations/content/it/errors/multi-catch.yaml create mode 100644 translations/content/it/errors/null-in-switch.yaml create mode 100644 translations/content/it/errors/optional-chaining.yaml create mode 100644 translations/content/it/errors/optional-orelsethrow.yaml create mode 100644 translations/content/it/errors/record-based-errors.yaml create mode 100644 translations/content/it/errors/require-nonnull-else.yaml create mode 100644 translations/content/it/io/deserialization-filters.yaml create mode 100644 translations/content/it/io/file-memory-mapping.yaml create mode 100644 translations/content/it/io/files-mismatch.yaml create mode 100644 translations/content/it/io/http-client.yaml create mode 100644 translations/content/it/io/inputstream-transferto.yaml create mode 100644 translations/content/it/io/io-class-console-io.yaml create mode 100644 translations/content/it/io/path-of.yaml create mode 100644 translations/content/it/io/reading-files.yaml create mode 100644 translations/content/it/io/try-with-resources-effectively-final.yaml create mode 100644 translations/content/it/io/writing-files.yaml create mode 100644 translations/content/it/language/compact-canonical-constructor.yaml create mode 100644 translations/content/it/language/compact-source-files.yaml create mode 100644 translations/content/it/language/default-interface-methods.yaml create mode 100644 translations/content/it/language/diamond-operator.yaml create mode 100644 translations/content/it/language/exhaustive-switch.yaml create mode 100644 translations/content/it/language/flexible-constructor-bodies.yaml create mode 100644 translations/content/it/language/guarded-patterns.yaml create mode 100644 translations/content/it/language/markdown-javadoc-comments.yaml create mode 100644 translations/content/it/language/module-import-declarations.yaml create mode 100644 translations/content/it/language/pattern-matching-instanceof.yaml create mode 100644 translations/content/it/language/pattern-matching-switch.yaml create mode 100644 translations/content/it/language/primitive-types-in-patterns.yaml create mode 100644 translations/content/it/language/private-interface-methods.yaml create mode 100644 translations/content/it/language/record-patterns.yaml create mode 100644 translations/content/it/language/records-for-data-classes.yaml create mode 100644 translations/content/it/language/sealed-classes.yaml create mode 100644 translations/content/it/language/static-members-in-inner-classes.yaml create mode 100644 translations/content/it/language/static-methods-in-interfaces.yaml create mode 100644 translations/content/it/language/switch-expressions.yaml create mode 100644 translations/content/it/language/text-blocks-for-multiline-strings.yaml create mode 100644 translations/content/it/language/type-inference-with-var.yaml create mode 100644 translations/content/it/language/unnamed-variables.yaml create mode 100644 translations/content/it/security/key-derivation-functions.yaml create mode 100644 translations/content/it/security/pem-encoding.yaml create mode 100644 translations/content/it/security/random-generator.yaml create mode 100644 translations/content/it/security/strong-random.yaml create mode 100644 translations/content/it/security/tls-default.yaml create mode 100644 translations/content/it/streams/collectors-flatmapping.yaml create mode 100644 translations/content/it/streams/optional-ifpresentorelse.yaml create mode 100644 translations/content/it/streams/optional-or.yaml create mode 100644 translations/content/it/streams/predicate-not.yaml create mode 100644 translations/content/it/streams/stream-gatherers.yaml create mode 100644 translations/content/it/streams/stream-iterate-predicate.yaml create mode 100644 translations/content/it/streams/stream-mapmulti.yaml create mode 100644 translations/content/it/streams/stream-of-nullable.yaml create mode 100644 translations/content/it/streams/stream-takewhile-dropwhile.yaml create mode 100644 translations/content/it/streams/stream-tolist.yaml create mode 100644 translations/content/it/streams/virtual-thread-executor.yaml create mode 100644 translations/content/it/strings/string-chars-stream.yaml create mode 100644 translations/content/it/strings/string-formatted.yaml create mode 100644 translations/content/it/strings/string-indent-transform.yaml create mode 100644 translations/content/it/strings/string-isblank.yaml create mode 100644 translations/content/it/strings/string-lines.yaml create mode 100644 translations/content/it/strings/string-repeat.yaml create mode 100644 translations/content/it/strings/string-strip.yaml create mode 100644 translations/content/it/tooling/aot-class-preloading.yaml create mode 100644 translations/content/it/tooling/built-in-http-server.yaml create mode 100644 translations/content/it/tooling/compact-object-headers.yaml create mode 100644 translations/content/it/tooling/jfr-profiling.yaml create mode 100644 translations/content/it/tooling/jshell-prototyping.yaml create mode 100644 translations/content/it/tooling/junit6-with-jspecify.yaml create mode 100644 translations/content/it/tooling/multi-file-source.yaml create mode 100644 translations/content/it/tooling/single-file-execution.yaml create mode 100644 translations/strings/it.yaml diff --git a/html-generators/locales.properties b/html-generators/locales.properties index 1013c65..c3d80ce 100644 --- a/html-generators/locales.properties +++ b/html-generators/locales.properties @@ -8,3 +8,4 @@ ar=🇸🇦 العربية fr=🇫🇷 Français ja=🇯🇵 日本語 ko=🇰🇷 한국어 +it=🇮🇹 Italiano diff --git a/translations/content/it/collections/collectors-teeing.yaml b/translations/content/it/collections/collectors-teeing.yaml new file mode 100644 index 0000000..d042758 --- /dev/null +++ b/translations/content/it/collections/collectors-teeing.yaml @@ -0,0 +1,18 @@ +--- +title: Collectors.teeing() +oldApproach: Due passaggi +modernApproach: teeing() +summary: "Calcola due aggregazioni in un unico passaggio dello stream." +explanation: "Collectors.teeing() invia ogni elemento a due collector downstream e unisce i risultati. Evita di scorrere i dati due volte o di usare un accumulatore mutabile." +whyModernWins: +- icon: ⚡ + title: Passaggio singolo + desc: "Elabora lo stream una volta invece di due." +- icon: 🧩 + title: Componibile + desc: "Combina qualsiasi due collector con una funzione di unione." +- icon: 🔒 + title: Risultato immutabile + desc: "Unisci direttamente in un record o value object." +support: + description: Ampiamente disponibile dal JDK 12 (marzo 2019) diff --git a/translations/content/it/collections/copying-collections-immutably.yaml b/translations/content/it/collections/copying-collections-immutably.yaml new file mode 100644 index 0000000..46eb60a --- /dev/null +++ b/translations/content/it/collections/copying-collections-immutably.yaml @@ -0,0 +1,18 @@ +--- +title: Copia di collezioni in modo immutabile +oldApproach: Copia manuale + Wrap +modernApproach: List.copyOf() +summary: "Crea una copia immutabile di qualsiasi collezione in una chiamata." +explanation: "List.copyOf(), Set.copyOf() e Map.copyOf() creano snapshot immutabili di collezioni esistenti. Se la sorgente è già una collezione immutabile, non viene effettuata alcuna copia." +whyModernWins: +- icon: ⚡ + title: Copia intelligente + desc: "Salta la copia se la sorgente è già immutabile." +- icon: 📏 + title: Una chiamata + desc: "Nessuna costruzione manuale di ArrayList + wrapping." +- icon: 🛡️ + title: Copia difensiva + desc: "Le modifiche all'originale non influenzano la copia." +support: + description: Ampiamente disponibile dal JDK 10 (marzo 2018) diff --git a/translations/content/it/collections/immutable-list-creation.yaml b/translations/content/it/collections/immutable-list-creation.yaml new file mode 100644 index 0000000..5924cc4 --- /dev/null +++ b/translations/content/it/collections/immutable-list-creation.yaml @@ -0,0 +1,18 @@ +--- +title: Creazione di liste immutabili +oldApproach: Wrapping verboso +modernApproach: List.of() +summary: "Crea liste immutabili in un'unica espressione pulita." +explanation: "List.of() crea una lista veramente immutabile — nessun wrapping, nessuna copia difensiva. È ostile ai null (rifiuta elementi null) e strutturalmente immutabile. Il vecchio modo richiedeva tre chiamate annidate." +whyModernWins: +- icon: 📏 + title: Una chiamata + desc: "Sostituisci tre chiamate annidate con un singolo metodo factory." +- icon: 🔒 + title: Veramente immutabile + desc: "Non è solo un wrapper — la lista stessa è immutabile." +- icon: 🛡️ + title: Null-safe + desc: "Rifiuta gli elementi null al momento della creazione, fallendo rapidamente." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/collections/immutable-map-creation.yaml b/translations/content/it/collections/immutable-map-creation.yaml new file mode 100644 index 0000000..f1be400 --- /dev/null +++ b/translations/content/it/collections/immutable-map-creation.yaml @@ -0,0 +1,18 @@ +--- +title: Creazione di mappe immutabili +oldApproach: Pattern Builder per Map +modernApproach: Map.of() +summary: "Crea mappe immutabili inline senza un builder." +explanation: "Map.of() accetta coppie chiave-valore inline e restituisce una mappa immutabile. Per più di 10 voci, usa Map.ofEntries() con coppie Map.entry()." +whyModernWins: +- icon: 📏 + title: Creazione inline + desc: "Non serve una mappa mutabile temporanea." +- icon: 🔒 + title: Risultato immutabile + desc: "La mappa non può essere modificata dopo la creazione." +- icon: 🚫 + title: Nessuna chiave/valore null + desc: "Le voci null vengono rifiutate immediatamente." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/collections/immutable-set-creation.yaml b/translations/content/it/collections/immutable-set-creation.yaml new file mode 100644 index 0000000..45d4187 --- /dev/null +++ b/translations/content/it/collections/immutable-set-creation.yaml @@ -0,0 +1,18 @@ +--- +title: Creazione di set immutabili +oldApproach: Wrapping verboso +modernApproach: Set.of() +summary: "Crea set immutabili con una singola chiamata factory." +explanation: "Set.of() crea un set veramente immutabile che rifiuta null e elementi duplicati al momento della creazione. Niente più wrapping di set mutabili." +whyModernWins: +- icon: 📏 + title: Conciso + desc: "Una riga invece di tre chiamate annidate." +- icon: 🚫 + title: Rileva duplicati + desc: "Lancia un'eccezione se passi accidentalmente elementi duplicati." +- icon: 🔒 + title: Immutabile + desc: "Nessuna aggiunta/rimozione possibile dopo la creazione." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/collections/map-entry-factory.yaml b/translations/content/it/collections/map-entry-factory.yaml new file mode 100644 index 0000000..780b375 --- /dev/null +++ b/translations/content/it/collections/map-entry-factory.yaml @@ -0,0 +1,18 @@ +--- +title: Factory Map.entry() +oldApproach: SimpleEntry +modernApproach: Map.entry() +summary: "Crea voci di mappa con un metodo factory pulito." +explanation: "Map.entry() sostituisce il verboso costruttore AbstractMap.SimpleEntry. Restituisce una voce immutabile, rendendola ideale per Map.ofEntries() e le operazioni stream." +whyModernWins: +- icon: 📏 + title: Conciso + desc: "Una riga invece di tre con un'intenzione più chiara." +- icon: 🔒 + title: Immutabile + desc: "La voce restituita non può essere modificata." +- icon: 🧩 + title: Componibile + desc: "Funziona perfettamente con Map.ofEntries() per mappe grandi." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/collections/reverse-list-iteration.yaml b/translations/content/it/collections/reverse-list-iteration.yaml new file mode 100644 index 0000000..6aae18b --- /dev/null +++ b/translations/content/it/collections/reverse-list-iteration.yaml @@ -0,0 +1,18 @@ +--- +title: Iterazione inversa di lista +oldApproach: ListIterator manuale +modernApproach: reversed() +summary: "Itera su una lista in ordine inverso con un ciclo for-each pulito." +explanation: "Il metodo reversed() di SequencedCollection restituisce una vista ordinata in senso inverso della lista. Questa vista è supportata dalla lista originale, quindi non si verifica alcuna copia. La sintassi del ciclo for potenziato rende l'iterazione inversa leggibile quanto quella diretta." +whyModernWins: +- icon: 📖 + title: Sintassi naturale + desc: "Ciclo for potenziato invece del verboso ListIterator." +- icon: ⚡ + title: Nessuna copia + desc: "reversed() restituisce una vista — nessun overhead di prestazioni." +- icon: 🧩 + title: API coerente + desc: "Funziona su List, Deque, SortedSet in modo uniforme." +support: + description: Ampiamente disponibile dal JDK 21 LTS (settembre 2023) diff --git a/translations/content/it/collections/sequenced-collections.yaml b/translations/content/it/collections/sequenced-collections.yaml new file mode 100644 index 0000000..486b78e --- /dev/null +++ b/translations/content/it/collections/sequenced-collections.yaml @@ -0,0 +1,18 @@ +--- +title: Collezioni sequenziate +oldApproach: Aritmetica degli indici +modernApproach: getFirst/getLast +summary: "Accedi ai primi/ultimi elementi e alle viste inverse con metodi API puliti." +explanation: "SequencedCollection aggiunge getFirst(), getLast(), reversed(), addFirst(), addLast() a List, Deque, SortedSet e LinkedHashSet. Niente più aritmetica size-1 o iterazione inversa manuale." +whyModernWins: +- icon: 📖 + title: Auto-documentante + desc: "getLast() è più chiaro di get(size()-1)." +- icon: 🔄 + title: Vista invertita + desc: "reversed() fornisce una vista — nessuna copia necessaria." +- icon: 🧩 + title: API uniforme + desc: "Funziona allo stesso modo su List, Deque, SortedSet." +support: + description: Ampiamente disponibile dal JDK 21 LTS (settembre 2023) diff --git a/translations/content/it/collections/stream-toarray-typed.yaml b/translations/content/it/collections/stream-toarray-typed.yaml new file mode 100644 index 0000000..cdbff94 --- /dev/null +++ b/translations/content/it/collections/stream-toarray-typed.yaml @@ -0,0 +1,18 @@ +--- +title: Stream toArray tipizzato +oldApproach: Copia manuale dell'array +modernApproach: toArray(generatore) +summary: "Converti gli stream in array tipizzati con un riferimento a metodo." +explanation: "Il metodo toArray(IntFunction) crea un array correttamente tipizzato da uno stream. Il generatore (String[]::new) indica allo stream quale tipo di array creare." +whyModernWins: +- icon: 🎯 + title: Type-safe + desc: "Nessun cast a Object[] — il tipo dell'array è corretto." +- icon: 🔗 + title: Concatenabile + desc: "Funziona alla fine di qualsiasi pipeline stream." +- icon: 📏 + title: Conciso + desc: "Un'espressione sostituisce il loop manuale." +support: + description: Ampiamente disponibile dal JDK 8 (marzo 2014) diff --git a/translations/content/it/collections/unmodifiable-collectors.yaml b/translations/content/it/collections/unmodifiable-collectors.yaml new file mode 100644 index 0000000..0fd0a49 --- /dev/null +++ b/translations/content/it/collections/unmodifiable-collectors.yaml @@ -0,0 +1,18 @@ +--- +title: Collector non modificabili +oldApproach: collectingAndThen +modernApproach: stream.toList() +summary: "Raccogli direttamente in una lista non modificabile con stream.toList()." +explanation: "Java 10 ha aggiunto toUnmodifiableList(), toUnmodifiableSet() e toUnmodifiableMap() per sostituire il verboso wrapper collectingAndThen. Per le liste in particolare, stream.toList() di Java 16 fornisce un'alternativa ancora più semplice — nessuna chiamata a collect(). Usa toUnmodifiableSet() e toUnmodifiableMap() per altri tipi di collezione." +whyModernWins: +- icon: 📏 + title: Il più breve + desc: "stream.toList() non necessita di collect() né dell'importazione di Collectors." +- icon: 🔒 + title: Immutabile + desc: "Il risultato non può essere modificato — nessuna mutazione accidentale." +- icon: 📖 + title: Leggibile + desc: "Si legge naturalmente come passo terminale di qualsiasi pipeline stream." +support: + description: Ampiamente disponibile dal JDK 16 (marzo 2021) diff --git a/translations/content/it/concurrency/completablefuture-chaining.yaml b/translations/content/it/concurrency/completablefuture-chaining.yaml new file mode 100644 index 0000000..fdea0a2 --- /dev/null +++ b/translations/content/it/concurrency/completablefuture-chaining.yaml @@ -0,0 +1,18 @@ +--- +title: Concatenazione CompletableFuture +oldApproach: Future.get() bloccante +modernApproach: CompletableFuture +summary: "Concatena operazioni asincrone senza bloccare, usando CompletableFuture." +explanation: "CompletableFuture abilita pipeline asincrone non bloccanti. Concatena le operazioni con thenApply, thenCompose, thenAccept. Gestisci gli errori con exceptionally(). Combina più future con allOf/anyOf." +whyModernWins: +- icon: 🔗 + title: Concatenabile + desc: "Componi i passi asincroni in una pipeline leggibile." +- icon: 🚫 + title: Non bloccante + desc: "Nessun thread rimane inattivo ad aspettare i risultati." +- icon: 🛡️ + title: Gestione degli errori + desc: "exceptionally() e handle() per un recupero pulito degli errori." +support: + description: Ampiamente disponibile dal JDK 8 (marzo 2014) diff --git a/translations/content/it/concurrency/concurrent-http-virtual.yaml b/translations/content/it/concurrency/concurrent-http-virtual.yaml new file mode 100644 index 0000000..e2bc8af --- /dev/null +++ b/translations/content/it/concurrency/concurrent-http-virtual.yaml @@ -0,0 +1,18 @@ +--- +title: HTTP concorrente con thread virtuali +oldApproach: Pool di thread + URLConnection +modernApproach: Thread virtuali + HttpClient +summary: "Recupera molti URL in modo concorrente con thread virtuali e HttpClient." +explanation: "I thread virtuali rendono pratico creare un thread per richiesta HTTP. Combinati con HttpClient, questo sostituisce i complessi pattern di callback asincroni con semplice codice bloccante che scala." +whyModernWins: +- icon: ♾️ + title: Thread per richiesta + desc: "Nessun dimensionamento del pool — un thread virtuale per URL." +- icon: 📖 + title: Codice semplice + desc: "Scrivi codice bloccante semplice." +- icon: ⚡ + title: Alta produttività + desc: "Migliaia di richieste concorrenti con risorse minime." +support: + description: Ampiamente disponibile dal JDK 21 LTS (settembre 2023) diff --git a/translations/content/it/concurrency/executor-try-with-resources.yaml b/translations/content/it/concurrency/executor-try-with-resources.yaml new file mode 100644 index 0000000..15d04b0 --- /dev/null +++ b/translations/content/it/concurrency/executor-try-with-resources.yaml @@ -0,0 +1,18 @@ +--- +title: Chiusura automatica ExecutorService +oldApproach: Shutdown manuale +modernApproach: try-with-resources +summary: "Usa try-with-resources per lo shutdown automatico dell'executor." +explanation: "Da Java 19, ExecutorService implementa AutoCloseable. Il metodo close() chiama shutdown() e attende il completamento dei task. Niente più pattern try/finally per lo shutdown manuale." +whyModernWins: +- icon: 🧹 + title: Pulizia automatica + desc: "Lo shutdown avviene automaticamente quando il blocco termina." +- icon: 🛡️ + title: Nessuna perdita + desc: "L'executor si spegne sempre, anche se si verificano eccezioni." +- icon: 📖 + title: Pattern familiare + desc: "Stesso try-with-resources usato per file, connessioni, ecc." +support: + description: Ampiamente disponibile dal JDK 19 (settembre 2022) diff --git a/translations/content/it/concurrency/lock-free-lazy-init.yaml b/translations/content/it/concurrency/lock-free-lazy-init.yaml new file mode 100644 index 0000000..dacfaa4 --- /dev/null +++ b/translations/content/it/concurrency/lock-free-lazy-init.yaml @@ -0,0 +1,18 @@ +--- +title: Inizializzazione lazy senza lock +oldApproach: synchronized + volatile +modernApproach: StableValue +summary: "Sostituisci il double-checked locking con StableValue per singleton lazy." +explanation: "StableValue incapsula il pattern di inizializzazione lazy con la corretta thread safety. La JVM può ottimizzare il percorso di lettura dopo l'inizializzazione, rendendolo potenzialmente più veloce delle letture volatile." +whyModernWins: +- icon: 🧹 + title: Nessun boilerplate + desc: "Nessun volatile, synchronized o doppio controllo null." +- icon: ⚡ + title: Letture più veloci + desc: "La JVM può piegare le costanti dopo l'inizializzazione." +- icon: ✅ + title: Provabilmente corretto + desc: "Nessun bug di ordinamento sottile — la JVM lo gestisce." +support: + description: "Anteprima nel JDK 25 (JEP 502, StableValue). Richiede --enable-preview." diff --git a/translations/content/it/concurrency/process-api.yaml b/translations/content/it/concurrency/process-api.yaml new file mode 100644 index 0000000..2d66080 --- /dev/null +++ b/translations/content/it/concurrency/process-api.yaml @@ -0,0 +1,18 @@ +--- +title: API Process moderna +oldApproach: Runtime.exec() +modernApproach: ProcessHandle +summary: "Ispeziona e gestisci i processi OS con ProcessHandle." +explanation: "ProcessHandle fornisce PID, informazioni sul processo (comando, argomenti, tempo di avvio, utilizzo CPU), relazioni padre/figlio e distruzione del processo. Niente più accesso agli interni non documentati di Process." +whyModernWins: +- icon: 🔍 + title: Informazioni complete + desc: "Accedi a PID, comando, argomenti, tempo di avvio, utilizzo CPU." +- icon: 🌳 + title: Albero dei processi + desc: "Naviga tra padre, figli e discendenti." +- icon: 📊 + title: Monitoraggio + desc: "onExit() restituisce un CompletableFuture per il monitoraggio asincrono." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/concurrency/scoped-values.yaml b/translations/content/it/concurrency/scoped-values.yaml new file mode 100644 index 0000000..ece96f8 --- /dev/null +++ b/translations/content/it/concurrency/scoped-values.yaml @@ -0,0 +1,18 @@ +--- +title: Valori scoped +oldApproach: ThreadLocal +modernApproach: ScopedValue +summary: "Condividi dati attraverso gli stack di chiamate in modo sicuro senza le insidie di ThreadLocal." +explanation: "ScopedValue fornisce contesto immutabile, ereditabile e limitato allo scope. A differenza di ThreadLocal, i valori scoped vengono puliti automaticamente, funzionano con i thread virtuali e non possono essere mutati dai chiamati." +whyModernWins: +- icon: 🔒 + title: Immutabile + desc: "I chiamati possono leggere ma non modificare mai il valore scoped." +- icon: 🧹 + title: Pulizia automatica + desc: "Nessun remove() manuale — il valore è scoped al blocco." +- icon: ⚡ + title: Sicuro per thread virtuali + desc: "Funziona efficientemente con milioni di thread virtuali." +support: + description: "Finalizzato nel JDK 25 LTS (JEP 506, settembre 2025)." diff --git a/translations/content/it/concurrency/stable-values.yaml b/translations/content/it/concurrency/stable-values.yaml new file mode 100644 index 0000000..9884d4d --- /dev/null +++ b/translations/content/it/concurrency/stable-values.yaml @@ -0,0 +1,18 @@ +--- +title: Valori stabili +oldApproach: Double-checked locking +modernApproach: StableValue +summary: "Inizializzazione lazy thread-safe senza volatile o synchronized." +explanation: "StableValue fornisce un valore inizializzato in modo lazy e immutabile con thread safety integrata. Nessun double-checked locking, nessun campo volatile, nessun blocco synchronized. La JVM può persino ottimizzare il percorso di lettura dopo l'inizializzazione." +whyModernWins: +- icon: 🧹 + title: Zero boilerplate + desc: "Nessun volatile, synchronized o controlli null." +- icon: ⚡ + title: Ottimizzato dalla JVM + desc: "La JVM può piegare il valore dopo l'inizializzazione." +- icon: 🛡️ + title: Garantito una volta + desc: "Il supplier viene eseguito esattamente una volta, anche sotto contesa." +support: + description: "Anteprima nel JDK 25 (JEP 502). Richiede --enable-preview." diff --git a/translations/content/it/concurrency/structured-concurrency.yaml b/translations/content/it/concurrency/structured-concurrency.yaml new file mode 100644 index 0000000..48c3c1d --- /dev/null +++ b/translations/content/it/concurrency/structured-concurrency.yaml @@ -0,0 +1,18 @@ +--- +title: Concorrenza strutturata +oldApproach: Ciclo di vita del thread manuale +modernApproach: StructuredTaskScope +summary: "Gestisci i cicli di vita dei task concorrenti come un'unica unità di lavoro." +explanation: "La concorrenza strutturata tratta un gruppo di task concorrenti come un'unica operazione. Se un subtask fallisce, gli altri vengono annullati. Lo scope garantisce che non ci siano perdite di thread e fornisce chiare relazioni padre-figlio." +whyModernWins: +- icon: 🛡️ + title: Nessuna perdita di thread + desc: "Tutti i task biforcati completano prima che lo scope si chiuda." +- icon: ⚡ + title: Fallimento rapido + desc: "ShutdownOnFailure annulla i fratelli se uno fallisce." +- icon: 📐 + title: Struttura chiara + desc: "Il ciclo di vita del task corrisponde allo scope lessicale nel codice." +support: + description: "Anteprima nel JDK 25 (quinta anteprima, JEP 505). Richiede --enable-preview." diff --git a/translations/content/it/concurrency/thread-sleep-duration.yaml b/translations/content/it/concurrency/thread-sleep-duration.yaml new file mode 100644 index 0000000..c9e5d26 --- /dev/null +++ b/translations/content/it/concurrency/thread-sleep-duration.yaml @@ -0,0 +1,18 @@ +--- +title: Thread.sleep con Duration +oldApproach: Millisecondi +modernApproach: Duration +summary: "Usa Duration per valori di tempo auto-documentanti." +explanation: "Thread.sleep(Duration) rende l'unità di tempo esplicita. Non serve più indovinare se 5000 significa millisecondi o microsecondi. Funziona con Duration.ofSeconds, ofMillis, ofMinutes, ecc." +whyModernWins: +- icon: 📖 + title: Auto-documentante + desc: "Duration.ofSeconds(5) è inequivocabile." +- icon: 🛡️ + title: Sicuro per unità + desc: "Nessun rischio di passare accidentalmente microsecondi come millisecondi." +- icon: 🧩 + title: Componibile + desc: "Aritmetica Duration: plus(), multipliedBy(), ecc." +support: + description: Ampiamente disponibile dal JDK 19 (settembre 2022) diff --git a/translations/content/it/concurrency/virtual-threads.yaml b/translations/content/it/concurrency/virtual-threads.yaml new file mode 100644 index 0000000..1ec945f --- /dev/null +++ b/translations/content/it/concurrency/virtual-threads.yaml @@ -0,0 +1,18 @@ +--- +title: Thread virtuali +oldApproach: Thread di piattaforma +modernApproach: Thread virtuali +summary: "Crea milioni di thread virtuali leggeri invece di pesanti thread OS." +explanation: "I thread virtuali sono thread leggeri gestiti dalla JVM, non dal sistema operativo. Puoi crearne milioni senza dover dimensionare i thread pool. Sono ideali per task I/O-bound come chiamate HTTP e query al database." +whyModernWins: +- icon: ⚡ + title: Leggeri + desc: "I thread virtuali usano KB di memoria, i thread di piattaforma usano MB." +- icon: ♾️ + title: Scalabili + desc: "Crea milioni di thread — nessuna necessità di dimensionare i pool." +- icon: 🧹 + title: Modello semplice + desc: "Scrivi codice bloccante che scala come il codice asincrono." +support: + description: Ampiamente disponibile dal JDK 21 LTS (settembre 2023) diff --git a/translations/content/it/datetime/date-formatting.yaml b/translations/content/it/datetime/date-formatting.yaml new file mode 100644 index 0000000..245db40 --- /dev/null +++ b/translations/content/it/datetime/date-formatting.yaml @@ -0,0 +1,18 @@ +--- +title: Formattazione delle date +oldApproach: SimpleDateFormat +modernApproach: DateTimeFormatter +summary: "Formatta le date con DateTimeFormatter thread-safe e immutabile." +explanation: "DateTimeFormatter è immutabile e thread-safe, a differenza di SimpleDateFormat. Può essere memorizzato come costante e condiviso. Sono disponibili formatter predefiniti come ISO_LOCAL_DATE per i formati comuni." +whyModernWins: +- icon: 🛡️ + title: Thread-safe + desc: "Condividi i formatter tra i thread senza sincronizzazione." +- icon: 📋 + title: Formati integrati + desc: "ISO_LOCAL_DATE, ISO_INSTANT, ecc. per i formati standard." +- icon: 🔒 + title: Immutabile + desc: "Memorizza in sicurezza come costante static final." +support: + description: Ampiamente disponibile dal JDK 8 (marzo 2014) diff --git a/translations/content/it/datetime/duration-and-period.yaml b/translations/content/it/datetime/duration-and-period.yaml new file mode 100644 index 0000000..d5691f3 --- /dev/null +++ b/translations/content/it/datetime/duration-and-period.yaml @@ -0,0 +1,18 @@ +--- +title: Duration e Period +oldApproach: Aritmetica in millisecondi +modernApproach: Duration / Period +summary: "Calcola le differenze di tempo con Duration e Period type-safe." +explanation: "Duration è per quantità basate sul tempo (ore, minuti, secondi). Period è per quantità basate sulla data (anni, mesi, giorni). ChronoUnit.between() per differenze semplici. Tutti gestiscono correttamente i casi limite." +whyModernWins: +- icon: 🎯 + title: Type-safe + desc: "Duration per il tempo, Period per le date — nessuna confusione." +- icon: 🛡️ + title: Calcoli corretti + desc: "Gestisce le transizioni DST, gli anni bisestili e i secondi intercalari." +- icon: 📖 + title: Leggibile + desc: "ChronoUnit.DAYS.between() si legge come in inglese." +support: + description: Ampiamente disponibile dal JDK 8 (marzo 2014) diff --git a/translations/content/it/datetime/hex-format.yaml b/translations/content/it/datetime/hex-format.yaml new file mode 100644 index 0000000..2a13b98 --- /dev/null +++ b/translations/content/it/datetime/hex-format.yaml @@ -0,0 +1,18 @@ +--- +title: HexFormat +oldApproach: Conversione esadecimale manuale +modernApproach: HexFormat +summary: "Converti tra stringhe esadecimali e array di byte con HexFormat." +explanation: "HexFormat fornisce codifica/decodifica esadecimale bidirezionale per byte, interi e array. Configura delimitatori, prefisso, suffisso e maiuscole/minuscole. Niente più formattazione o parsing manuale." +whyModernWins: +- icon: 📐 + title: Bidirezionale + desc: "Converti byte→hex e hex→byte con un'unica API." +- icon: 🔧 + title: Configurabile + desc: "Delimitatori, prefisso, suffisso, maiuscole/minuscole." +- icon: 📦 + title: Supporto array + desc: "Codifica/decodifica interi array di byte in una volta." +support: + description: Ampiamente disponibile dal JDK 17 LTS (settembre 2021) diff --git a/translations/content/it/datetime/instant-precision.yaml b/translations/content/it/datetime/instant-precision.yaml new file mode 100644 index 0000000..9934693 --- /dev/null +++ b/translations/content/it/datetime/instant-precision.yaml @@ -0,0 +1,18 @@ +--- +title: Instant con precisione al nanosecondo +oldApproach: Millisecondi +modernApproach: Nanosecondi +summary: "Ottieni timestamp con precisione al microsecondo o nanosecondo." +explanation: "Java 9 ha migliorato la risoluzione dell'orologio così che Instant.now() cattura la precisione al microsecondo sulla maggior parte delle piattaforme (nanosecondo su alcune). Il vecchio currentTimeMillis() fornisce solo millisecondi." +whyModernWins: +- icon: 🎯 + title: Maggiore precisione + desc: "Timestamp al microsecondo/nanosecondo invece che al millisecondo." +- icon: 📐 + title: Type-safe + desc: "Instant porta la sua precisione — nessun long ambiguo." +- icon: 🌐 + title: Basato su UTC + desc: "Instant è sempre in UTC — nessuna confusione di fuso orario." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/datetime/java-time-basics.yaml b/translations/content/it/datetime/java-time-basics.yaml new file mode 100644 index 0000000..2284f22 --- /dev/null +++ b/translations/content/it/datetime/java-time-basics.yaml @@ -0,0 +1,18 @@ +--- +title: Basi dell'API java.time +oldApproach: Date + Calendar +modernApproach: java.time.* +summary: "Usa tipi di data/ora immutabili e chiari invece di Date e Calendar." +explanation: "java.time fornisce LocalDate, LocalTime, LocalDateTime, Instant, ZonedDateTime — tutti immutabili e thread-safe. I mesi sono indicizzati a partire da 1. Niente più confusione con Calendar.JANUARY = 0." +whyModernWins: +- icon: 🔒 + title: Immutabile + desc: "I valori di data/ora non possono essere modificati accidentalmente." +- icon: 📖 + title: API chiara + desc: "Month.JANUARY, non 0. DayOfWeek.MONDAY, non 2." +- icon: 🛡️ + title: Thread-safe + desc: "Nessuna sincronizzazione necessaria — condividi liberamente tra i thread." +support: + description: Ampiamente disponibile dal JDK 8 (marzo 2014) diff --git a/translations/content/it/datetime/math-clamp.yaml b/translations/content/it/datetime/math-clamp.yaml new file mode 100644 index 0000000..6be1ec0 --- /dev/null +++ b/translations/content/it/datetime/math-clamp.yaml @@ -0,0 +1,18 @@ +--- +title: Math.clamp() +oldApproach: min/max annidati +modernApproach: Math.clamp() +summary: "Vincola un valore tra limiti con una singola chiamata chiara." +explanation: "Math.clamp(value, min, max) vincola un valore all'intervallo [min, max]. Più chiaro dei Math.min/Math.max annidati e disponibile per int, long, float e double." +whyModernWins: +- icon: 📖 + title: Auto-documentante + desc: "clamp(value, min, max) è inequivocabile." +- icon: 🛡️ + title: Meno soggetto a errori + desc: "Nessun rischio di invertire accidentalmente l'ordine min/max." +- icon: 🎯 + title: Tutti i tipi numerici + desc: "Funziona con int, long, float e double." +support: + description: Ampiamente disponibile dal JDK 21 LTS (settembre 2023) diff --git a/translations/content/it/enterprise/ejb-timer-vs-jakarta-scheduler.yaml b/translations/content/it/enterprise/ejb-timer-vs-jakarta-scheduler.yaml new file mode 100644 index 0000000..9c5bfd0 --- /dev/null +++ b/translations/content/it/enterprise/ejb-timer-vs-jakarta-scheduler.yaml @@ -0,0 +1,18 @@ +--- +title: Timer EJB vs Jakarta Scheduler +oldApproach: TimerService EJB +modernApproach: ManagedScheduledExecutorService +summary: "Sostituisci i pesanti timer EJB con ManagedScheduledExecutorService di Jakarta Concurrency per una pianificazione più semplice." +explanation: "I timer EJB richiedono un bean @Stateless o @Singleton con un callback @Timeout ed espressioni di pianificazione basate su XML o annotazioni. Jakarta Concurrency fornisce ManagedScheduledExecutorService, che usa la familiare API di pianificazione java.util.concurrent. Il risultato è meno boilerplate, test unitari più facili e nessuna dipendenza dal container EJB." +whyModernWins: +- icon: 🪶 + title: Boilerplate ridotto + desc: "Nessun callback @Timeout o ScheduleExpression — usa l'API standard ScheduledExecutorService." +- icon: 🧪 + title: Migliore testabilità + desc: "Metodi semplici e mock dell'executor rendono i test unitari semplici senza container EJB." +- icon: ☁️ + title: Cloud-native friendly + desc: "Gli executor gestiti si integrano con il ciclo di vita del container e funzionano in runtime leggeri." +support: + description: "Disponibile da Jakarta EE 10 / Concurrency 3.0" diff --git a/translations/content/it/enterprise/ejb-vs-cdi.yaml b/translations/content/it/enterprise/ejb-vs-cdi.yaml new file mode 100644 index 0000000..3f0773f --- /dev/null +++ b/translations/content/it/enterprise/ejb-vs-cdi.yaml @@ -0,0 +1,18 @@ +--- +title: EJB vs CDI +oldApproach: EJB +modernApproach: Bean CDI +summary: "Sostituisci gli EJB pesanti con bean CDI leggeri per dependency injection e transazioni." +explanation: "CDI (Contexts and Dependency Injection) fornisce la stessa dependency injection e gestione delle transazioni degli EJB, ma come semplici classi Java senza interfacce o superclassi specifiche per container. Gli scope come @ApplicationScoped e @RequestScoped controllano il ciclo di vita, e @Transactional sostituisce la semantica transazionale obbligatoria degli EJB." +whyModernWins: +- icon: 🪶 + title: Leggero + desc: "I bean CDI sono semplici classi Java senza interfacce o descrittori EJB." +- icon: 💉 + title: Iniezione unificata + desc: "@Inject funziona per ogni bean gestito, risorse JAX-RS e componenti Jakarta EE." +- icon: 🧪 + title: Test unitari facili + desc: "Le classi semplici senza overhead del proxy EJB sono facili da istanziare e simulare." +support: + description: Ampiamente disponibile da Jakarta EE 8 / Java 11 diff --git a/translations/content/it/enterprise/jdbc-resultset-vs-jpa-criteria.yaml b/translations/content/it/enterprise/jdbc-resultset-vs-jpa-criteria.yaml new file mode 100644 index 0000000..1577233 --- /dev/null +++ b/translations/content/it/enterprise/jdbc-resultset-vs-jpa-criteria.yaml @@ -0,0 +1,18 @@ +--- +title: Mapping JDBC ResultSet vs API Criteria JPA +oldApproach: JDBC ResultSet +modernApproach: API Criteria JPA +summary: "Sostituisci il mapping manuale JDBC ResultSet con l'API Criteria type-safe di JPA per le query dinamiche." +explanation: "Il JDBC grezzo richiede la costruzione di stringhe SQL, l'impostazione dei parametri per indice e il mapping manuale di ogni colonna ResultSet — un processo soggetto a errori che si rompe silenziosamente quando le colonne cambiano. L'API Criteria JPA costruisce query programmaticamente usando un pattern builder type-safe. I nomi delle colonne vengono validati rispetto al modello entità, il mapping dei risultati è automatico e le query dinamiche complesse si compongono in modo pulito senza concatenazione di stringhe." +whyModernWins: +- icon: 🔒 + title: Query type-safe + desc: "Il builder Criteria rileva i nomi dei campi e le mancate corrispondenze di tipo in fase di compilazione." +- icon: 🗺️ + title: Mapping automatico + desc: "JPA mappa le righe dei risultati in oggetti entità — nessuna estrazione manuale colonna per colonna." +- icon: 🧩 + title: Predicati componibili + desc: "Le clausole where dinamiche si costruiscono in modo pulito con and(), or() e oggetti Predicate riutilizzabili." +support: + description: Ampiamente disponibile da Jakarta EE 8 / Java 11 diff --git a/translations/content/it/enterprise/jdbc-vs-jooq.yaml b/translations/content/it/enterprise/jdbc-vs-jooq.yaml new file mode 100644 index 0000000..4ee139f --- /dev/null +++ b/translations/content/it/enterprise/jdbc-vs-jooq.yaml @@ -0,0 +1,18 @@ +--- +title: JDBC vs jOOQ +oldApproach: JDBC grezzo +modernApproach: jOOQ SQL DSL +summary: "Sostituisci il SQL basato su stringhe JDBC con il DSL SQL type-safe e fluente di jOOQ." +explanation: "jOOQ (Java Object Oriented Querying) genera codice Java dallo schema del database, trasformando i nomi di tabelle e colonne in costanti Java type-safe. Il DSL fluente rispecchia la sintassi SQL così le query sono leggibili e componibili. Tutti i parametri sono legati automaticamente, eliminando il rischio di SQL injection. A differenza di JPA/JPQL, jOOQ abbraccia pienamente SQL — funzioni finestra, CTE, clausole RETURNING ed estensioni specifiche del vendor sono tutte di prima classe." +whyModernWins: +- icon: 🔒 + title: Colonne type-safe + desc: "I nomi delle colonne sono costanti Java generate — i typo e le mancate corrispondenze di tipo diventano errori del compilatore invece di fallimenti runtime." +- icon: 📖 + title: Fluidità SQL + desc: "Il DSL jOOQ rispecchia da vicino la sintassi SQL, così i JOIN complessi, le subquery e i CTE rimangono leggibili." +- icon: 🛡️ + title: Injection-free by design + desc: "I parametri sono sempre legati in modo sicuro — nessuna concatenazione di stringhe significa nessun rischio di SQL injection." +support: + description: "L'edizione open-source di jOOQ supporta tutti i principali database open-source; i database commerciali più vecchi richiedono una licenza a pagamento" diff --git a/translations/content/it/enterprise/jdbc-vs-jpa.yaml b/translations/content/it/enterprise/jdbc-vs-jpa.yaml new file mode 100644 index 0000000..7d0908d --- /dev/null +++ b/translations/content/it/enterprise/jdbc-vs-jpa.yaml @@ -0,0 +1,18 @@ +--- +title: JDBC vs JPA +oldApproach: JDBC +modernApproach: EntityManager JPA +summary: "Sostituisci il verboso boilerplate JDBC con l'object-relational mapping JPA e EntityManager." +explanation: "JPA (Jakarta Persistence API) mappa gli oggetti Java alle righe del database, eliminando la necessità di elaborare manualmente i ResultSet e concatenare stringhe SQL. EntityManager fornisce find(), persist() e query JPQL così lavori con oggetti di dominio invece di SQL grezzo, mentre il container gestisce il connection pooling e le transazioni." +whyModernWins: +- icon: 🗺️ + title: Mapping degli oggetti + desc: "Le entità sono semplici classi annotate — nessuna traduzione manuale ResultSet-a-oggetto." +- icon: 🔒 + title: Query type-safe + desc: "JPQL opera su tipi di entità e campi invece di stringhe di tabella e colonna grezze." +- icon: ⚡ + title: Cache integrata + desc: "La cache di primo e secondo livello riduce automaticamente i round-trip al database." +support: + description: Ampiamente disponibile da Jakarta EE 8 / Java 11 diff --git a/translations/content/it/enterprise/jndi-lookup-vs-cdi-injection.yaml b/translations/content/it/enterprise/jndi-lookup-vs-cdi-injection.yaml new file mode 100644 index 0000000..cae6714 --- /dev/null +++ b/translations/content/it/enterprise/jndi-lookup-vs-cdi-injection.yaml @@ -0,0 +1,18 @@ +--- +title: Lookup JNDI vs Iniezione CDI +oldApproach: Lookup JNDI +modernApproach: CDI @Inject +summary: "Sostituisci i fragili lookup JNDI basati su stringhe con l'iniezione CDI type-safe per le risorse gestite dal container." +explanation: "Il pattern JNDI tradizionale ti costringe a usare nomi di risorse basati su stringhe, gestire NamingException e gestire un InitialContext. L'iniezione CDI con @Inject (o @Resource per le risorse container) lascia che il container crei automaticamente le dipendenze. I typo diventano errori di compilazione, e le classi sono più facili da testare perché le dipendenze possono essere iniettate direttamente." +whyModernWins: +- icon: 🔒 + title: Wiring type-safe + desc: "Gli errori di iniezione vengono rilevati al momento del deploy, non a runtime tramite lookup di stringhe." +- icon: 🗑️ + title: Nessun boilerplate + desc: "Elimina la creazione di InitialContext, le stringhe JNDI e la gestione di NamingException." +- icon: 🧪 + title: Testabile + desc: "Le dipendenze sono campi iniettati, facilmente sostituibili con mock nei test unitari." +support: + description: Ampiamente disponibile da Jakarta EE 8 / Java 11 diff --git a/translations/content/it/enterprise/jpa-vs-jakarta-data.yaml b/translations/content/it/enterprise/jpa-vs-jakarta-data.yaml new file mode 100644 index 0000000..0905ee9 --- /dev/null +++ b/translations/content/it/enterprise/jpa-vs-jakarta-data.yaml @@ -0,0 +1,18 @@ +--- +title: JPA vs Jakarta Data +oldApproach: EntityManager JPA +modernApproach: Repository Jakarta Data +summary: "Dichiara un'interfaccia repository e lascia che Jakarta Data generi automaticamente l'implementazione DAO." +explanation: "Jakarta Data (Jakarta EE 11) trasforma l'accesso ai dati in una pura dichiarazione di interfaccia. Annoti un'interfaccia con @Repository ed estendi un tipo di repository integrato come CrudRepository. Il runtime genera l'implementazione — incluse le query derivate dai nomi dei metodi come findByName — quindi non c'è boilerplate EntityManager, nessuna stringa JPQL e nessun metodo save/find scritto a mano." +whyModernWins: +- icon: 🪄 + title: Zero boilerplate + desc: "Dichiara l'interfaccia; il container genera l'intera implementazione DAO al deploy." +- icon: 🔍 + title: Query derivate + desc: "I nomi dei metodi come findByNameAndStatus vengono analizzati automaticamente — nessun JPQL o SQL necessario." +- icon: 🔌 + title: Portabile + desc: "Qualsiasi runtime conforme a Jakarta EE 11 fornisce l'implementazione del repository senza vendor lock-in." +support: + description: "Disponibile da Jakarta EE 11 / Java 21 (2024)" diff --git a/translations/content/it/enterprise/jsf-managed-bean-vs-cdi-named.yaml b/translations/content/it/enterprise/jsf-managed-bean-vs-cdi-named.yaml new file mode 100644 index 0000000..037cb18 --- /dev/null +++ b/translations/content/it/enterprise/jsf-managed-bean-vs-cdi-named.yaml @@ -0,0 +1,18 @@ +--- +title: JSF Managed Bean vs CDI Named Bean +oldApproach: "@ManagedBean" +modernApproach: "@Named + CDI" +summary: "Sostituisci il deprecato JSF @ManagedBean con CDI @Named per un modello unificato di dependency injection." +explanation: "JSF's @ManagedBean e @ManagedProperty sono stati deprecati in Jakarta Faces 2.3 e rimossi in Jakarta EE 10. Il sostituto CDI usa @Named per esporre il bean alle espressioni EL e @Inject per il cablaggio delle dipendenze. Questo unifica il modello di bean: le pagine JSF, le risorse JAX-RS e gli EJB condividono tutti lo stesso container CDI." +whyModernWins: +- icon: 🔗 + title: Modello unificato + desc: "Un container CDI gestisce tutti i bean — JSF, REST e i livelli di servizio condividono la stessa iniezione." +- icon: 🗑️ + title: Meno boilerplate + desc: "@Inject sostituisce @ManagedProperty e il suo metodo setter richiesto." +- icon: 🔮 + title: A prova di futuro + desc: "@ManagedBean è rimosso in Jakarta EE 10; @Named è il sostituto supportato." +support: + description: "CDI @Named disponibile da Java EE 6; @ManagedBean rimosso in Jakarta EE 10" diff --git a/translations/content/it/enterprise/manual-transaction-vs-declarative.yaml b/translations/content/it/enterprise/manual-transaction-vs-declarative.yaml new file mode 100644 index 0000000..6e510a2 --- /dev/null +++ b/translations/content/it/enterprise/manual-transaction-vs-declarative.yaml @@ -0,0 +1,18 @@ +--- +title: Transazione JPA manuale vs @Transactional dichiarativa +oldApproach: Transazione manuale +modernApproach: "@Transactional" +summary: "Sostituisci i verbosi blocchi begin/commit/rollback con una singola annotazione @Transactional." +explanation: "La gestione manuale delle transazioni richiede chiamate esplicite a begin(), commit() e rollback() avvolte in blocchi try-catch — ogni metodo di servizio ripete questo boilerplate. L'annotazione @Transactional delega la gestione del ciclo di vita al container: inizia una transazione prima del metodo, esegue il commit in caso di successo e il rollback in caso di RuntimeException automaticamente." +whyModernWins: +- icon: 🗑️ + title: Nessun boilerplate + desc: "Un'annotazione sostituisce i ripetitivi blocchi try-catch begin/commit/rollback." +- icon: 🛡️ + title: Rollback più sicuro + desc: "Il container garantisce il rollback sulle eccezioni non controllate — nessun rischio di dimenticare il blocco catch." +- icon: 📐 + title: Controllo dichiarativo + desc: "Propagazione, isolamento e regole di rollback sono espressi come attributi dell'annotazione." +support: + description: Ampiamente disponibile da Jakarta EE 8 / Java 11 diff --git a/translations/content/it/enterprise/mdb-vs-reactive-messaging.yaml b/translations/content/it/enterprise/mdb-vs-reactive-messaging.yaml new file mode 100644 index 0000000..f5a28ae --- /dev/null +++ b/translations/content/it/enterprise/mdb-vs-reactive-messaging.yaml @@ -0,0 +1,18 @@ +--- +title: Message-Driven Bean vs Reactive Messaging +oldApproach: Message-Driven Bean +modernApproach: Reactive Messaging +summary: "Sostituisci i JMS Message-Driven Bean con MicroProfile Reactive Messaging per un'elaborazione degli eventi più semplice." +explanation: "I Message-Driven Bean richiedono l'implementazione di MessageListener, la configurazione delle proprietà di attivazione e la deserializzazione manuale dei messaggi JMS. MicroProfile Reactive Messaging usa una semplice annotazione @Incoming su un metodo che riceve oggetti tipizzati direttamente. La configurazione del canale è esternalizzata, rendendo il codice broker-agnostico e molto più facile da testare." +whyModernWins: +- icon: 🪶 + title: Codice minimale + desc: "Un singolo metodo @Incoming sostituisce la classe MDB, l'interfaccia MessageListener e la configurazione di attivazione." +- icon: 🔌 + title: Broker-agnostico + desc: "Cambia i connector Kafka, AMQP o JMS tramite configurazione senza modificare il codice dell'applicazione." +- icon: ☁️ + title: Adatto al cloud-native + desc: "La backpressure degli stream reattivi e il runtime leggero lo rendono ideale per i deployment containerizzati." +support: + description: "Disponibile da MicroProfile 4.0 / SmallRye Reactive Messaging" diff --git a/translations/content/it/enterprise/servlet-vs-jaxrs.yaml b/translations/content/it/enterprise/servlet-vs-jaxrs.yaml new file mode 100644 index 0000000..e647aec --- /dev/null +++ b/translations/content/it/enterprise/servlet-vs-jaxrs.yaml @@ -0,0 +1,18 @@ +--- +title: Servlet vs JAX-RS +oldApproach: HttpServlet +modernApproach: Risorsa JAX-RS +summary: "Sostituisci il verboso boilerplate HttpServlet con classi di risorse JAX-RS dichiarative." +explanation: "JAX-RS (Jakarta RESTful Web Services) consente di esporre endpoint REST usando semplici annotazioni come @GET, @Path e @Produces. Niente più parsing manuale dei parametri di richiesta o impostazione dei tipi di contenuto sulla risposta — il runtime gestisce automaticamente il marshalling e il routing." +whyModernWins: +- icon: 📐 + title: Routing dichiarativo + desc: "Le annotazioni definiscono il metodo HTTP, il percorso e il tipo di contenuto invece del dispatch imperativo if/else." +- icon: 🔄 + title: Marshalling automatico + desc: "Restituisci POJO direttamente; il runtime li serializza in JSON o XML in base a @Produces." +- icon: 🧪 + title: Test più facile + desc: "Le classi di risorse sono semplici oggetti Java, testabili senza un container servlet." +support: + description: Ampiamente disponibile da Jakarta EE 8 / Java 11 diff --git a/translations/content/it/enterprise/singleton-ejb-vs-cdi-application-scoped.yaml b/translations/content/it/enterprise/singleton-ejb-vs-cdi-application-scoped.yaml new file mode 100644 index 0000000..0919d7b --- /dev/null +++ b/translations/content/it/enterprise/singleton-ejb-vs-cdi-application-scoped.yaml @@ -0,0 +1,18 @@ +--- +title: Singleton EJB vs CDI @ApplicationScoped +oldApproach: "@Singleton EJB" +modernApproach: "@ApplicationScoped CDI" +summary: "Sostituisci i Singleton EJB con bean CDI @ApplicationScoped per una gestione più semplice dello stato condiviso." +explanation: "I Singleton EJB raggruppano la gestione della concorrenza (@Lock, @ConcurrencyManagement) e l'inizializzazione eager (@Startup) nel container EJB. Un bean CDI @ApplicationScoped ottiene lo stesso ciclo di vita a istanza singola con molta meno cerimonia. Quando è necessario il controllo della concorrenza, le utilità standard java.util.concurrent danno un controllo più granulare rispetto alle annotazioni di lock EJB." +whyModernWins: +- icon: 🪶 + title: Meno rumore di annotazioni + desc: "Nessun @ConcurrencyManagement, @Lock o @Startup — solo una singola annotazione @ApplicationScoped." +- icon: 🔧 + title: Concorrenza flessibile + desc: "Usa lock java.util.concurrent o volatile per la thread-safety di cui hai esattamente bisogno." +- icon: 🧪 + title: Test facile + desc: "I semplici bean CDI possono essere istanziati direttamente nei test senza un container EJB." +support: + description: Ampiamente disponibile da Jakarta EE 8 / Java 11 diff --git a/translations/content/it/enterprise/soap-vs-jakarta-rest.yaml b/translations/content/it/enterprise/soap-vs-jakarta-rest.yaml new file mode 100644 index 0000000..349e012 --- /dev/null +++ b/translations/content/it/enterprise/soap-vs-jakarta-rest.yaml @@ -0,0 +1,18 @@ +--- +title: Web Service SOAP vs Jakarta REST +oldApproach: JAX-WS / SOAP +modernApproach: Jakarta REST / JSON +summary: "Sostituisci i pesanti endpoint SOAP/WSDL con pulite risorse Jakarta REST che restituiscono JSON." +explanation: "I web service basati su SOAP si basano su contratti WSDL, marshalling XML e annotazioni JAX-WS che aggiungono un overhead significativo. Jakarta REST (ex JAX-RS) usa annotazioni intuitive come @GET, @Path e @Produces per esporre API RESTful JSON. Il modello di programmazione è più semplice, i payload sono più piccoli e l'approccio si allinea con il modo in cui i moderni microservizi comunicano." +whyModernWins: +- icon: 🪶 + title: Payload più leggeri + desc: "JSON è più compatto degli involucri XML SOAP, riducendo la larghezza di banda e l'overhead di parsing." +- icon: 📐 + title: Annotazioni semplici + desc: "@GET, @Path e @Produces sostituiscono la cerimonia di WSDL, @WebService e @WebMethod." +- icon: 🔌 + title: Pronto per microservizi + desc: "REST/JSON è lo standard per la comunicazione servizio-a-servizio nelle architetture cloud-native." +support: + description: Ampiamente disponibile da Jakarta EE 8 / Java 11 diff --git a/translations/content/it/enterprise/spring-api-versioning.yaml b/translations/content/it/enterprise/spring-api-versioning.yaml new file mode 100644 index 0000000..88bca7a --- /dev/null +++ b/translations/content/it/enterprise/spring-api-versioning.yaml @@ -0,0 +1,18 @@ +--- +title: Versionamento API Spring Framework 7 +oldApproach: Versionamento manuale del percorso URL +modernApproach: Versionamento API nativo +summary: "Sostituisci i controller duplicati con prefisso versione con il supporto nativo al versionamento API di Spring Framework 7." +explanation: "Prima di Spring Framework 7, il versionamento API richiedeva classi controller separate per versione (es. /api/v1/products, /api/v2/products), duplicando i mapping delle richieste e disperdendo la logica delle versioni su molti file. Spring Framework 7 introduce il versionamento nativo tramite un nuovo attributo version su @RequestMapping e le annotazioni correlate, più un hook configureApiVersioning in WebMvcConfigurer. La versione può essere risolta da un header di richiesta, un segmento del percorso URL o un parametro di query — tutto controllato in un unico posto." +whyModernWins: +- icon: 🗂️ + title: Nessuna duplicazione del controller + desc: "Tutte le versioni risiedono in una sola classe controller; solo i singoli metodi handler portano un attributo di versione." +- icon: ⚙️ + title: Strategia di versione centralizzata + desc: "Passa da header a URL o versionamento con parametro query in una singola chiamata configureApiVersioning." +- icon: 📈 + title: Evoluzione incrementale + desc: "Aggiungi una nuova versione a un metodo senza toccare endpoint non correlati o creare nuovi file controller." +support: + description: "Disponibile da Spring Framework 7.0 (richiede Java 17+)" diff --git a/translations/content/it/enterprise/spring-null-safety-jspecify.yaml b/translations/content/it/enterprise/spring-null-safety-jspecify.yaml new file mode 100644 index 0000000..02ce981 --- /dev/null +++ b/translations/content/it/enterprise/spring-null-safety-jspecify.yaml @@ -0,0 +1,18 @@ +--- +title: Spring Null Safety con JSpecify +oldApproach: Spring @NonNull/@Nullable +modernApproach: JSpecify @NullMarked +summary: "Spring 7 adotta le annotazioni JSpecify, rendendo non-null il default e riducendo il rumore delle annotazioni." +explanation: "Spring 5 e 6 hanno introdotto le proprie annotazioni di null safety nel package `org.springframework.lang`. Sebbene utili, erano specifiche del framework e richiedevano l'annotazione esplicita di ogni elemento non-null. Spring 7 migra a JSpecify, uno standard cross-ecosistema per la null safety. L'annotazione `@NullMarked` a livello di classe o package dichiara che tutti i tipi non annotati sono non-null per default. Solo i tipi effettivamente nullable necessitano dell'annotazione `@Nullable`, riducendo drasticamente la verbosità. Le annotazioni JSpecify sono riconosciute dai principali strumenti di analisi statica come NullAway, Error Prone e IntelliJ IDEA." +whyModernWins: +- icon: ✂️ + title: Non-null per default + desc: "@NullMarked rende tutti i tipi non annotati non-null, così solo le eccezioni nullable necessitano di annotazione." +- icon: 🌐 + title: Standard dell'ecosistema + desc: "Le annotazioni JSpecify sono uno standard cross-framework riconosciuto da NullAway, Error Prone e IDE." +- icon: 🔍 + title: Strumenti più ricchi + desc: "I moderni analizzatori statici comprendono il modello null di JSpecify e segnalano le violazioni in fase di compilazione." +support: + description: "Disponibile da Spring Framework 7.0 (richiede Java 17+)" diff --git a/translations/content/it/enterprise/spring-xml-config-vs-annotations.yaml b/translations/content/it/enterprise/spring-xml-config-vs-annotations.yaml new file mode 100644 index 0000000..23cee07 --- /dev/null +++ b/translations/content/it/enterprise/spring-xml-config-vs-annotations.yaml @@ -0,0 +1,18 @@ +--- +title: Configurazione Spring XML vs Annotation-Driven +oldApproach: Definizioni bean XML +modernApproach: Bean annotation-driven +summary: "Sostituisci le verbose definizioni di bean Spring XML con la configurazione annotation-driven concisa in Spring Boot." +explanation: "Le applicazioni Spring tradizionali cablano i bean attraverso file di configurazione XML, dichiarando ogni classe e le sue dipendenze come elementi verbosi. Sebbene il supporto alle annotazioni esistesse da Spring 2.5, XML rimase l'approccio dominante finché Spring Boot non introdusse la auto-configurazione. Spring Boot rileva i bean annotati con @Component, @Service, @Repository e @Controller tramite la scansione del classpath, soddisfa le dipendenze tramite constructor injection automaticamente e configura l'infrastruttura come DataSource dal classpath — eliminando tutti i file XML di cablaggio." +whyModernWins: +- icon: 🚫 + title: Nessun XML + desc: "@SpringBootApplication attiva la scansione dei componenti e la auto-configurazione, eliminando tutti i file XML di cablaggio." +- icon: 💉 + title: Constructor injection + desc: "Spring inietta le dipendenze tramite costruttori automaticamente, rendendo i bean più facili da testare e ragionare." +- icon: ⚡ + title: Auto-configurazione + desc: "Spring Boot configura DataSource, JPA e altra infrastruttura dal classpath senza boilerplate." +support: + description: "Ampiamente disponibile da Spring Boot 1.0 (aprile 2014); Spring Boot 3 richiede Java 17+" diff --git a/translations/content/it/errors/helpful-npe.yaml b/translations/content/it/errors/helpful-npe.yaml new file mode 100644 index 0000000..fdfaf3c --- /dev/null +++ b/translations/content/it/errors/helpful-npe.yaml @@ -0,0 +1,18 @@ +--- +title: NullPointerException utili +oldApproach: NPE criptiche +modernApproach: NPE dettagliate +summary: "La JVM indica automaticamente quale variabile era null." +explanation: "Le NPE utili descrivono quale espressione era null e quale operazione è fallita. Sono abilitate per default da Java 14 — nessuna modifica al codice necessaria, basta aggiornare il JDK." +whyModernWins: +- icon: 🔍 + title: Variabile esatta + desc: "Il messaggio nomina la variabile null nella catena." +- icon: ⚡ + title: Debug più veloce + desc: "Non serve più indovinare quale delle 5 chiamate concatenate era null." +- icon: 🆓 + title: Aggiornamento gratuito + desc: "Nessuna modifica al codice — basta eseguire su JDK 14+." +support: + description: Ampiamente disponibile dal JDK 14 (marzo 2020) diff --git a/translations/content/it/errors/multi-catch.yaml b/translations/content/it/errors/multi-catch.yaml new file mode 100644 index 0000000..19dfc65 --- /dev/null +++ b/translations/content/it/errors/multi-catch.yaml @@ -0,0 +1,18 @@ +--- +title: Gestione multi-catch delle eccezioni +oldApproach: Blocchi catch separati +modernApproach: Multi-catch +summary: "Cattura più tipi di eccezione in un singolo blocco catch." +explanation: "Multi-catch gestisce più tipi di eccezione con lo stesso codice. La variabile eccezione è effettivamente final, quindi puoi rilanciare senza wrapping." +whyModernWins: +- icon: 📏 + title: DRY + desc: "La stessa logica di gestione scritta una volta invece di tre." +- icon: 🔄 + title: Rilanciabile + desc: "L'eccezione catturata può essere rilanciata con il suo tipo preciso." +- icon: 📖 + title: Scansionabile + desc: "Tutti i tipi gestiti sono visibili in un posto." +support: + description: Ampiamente disponibile dal JDK 7 (luglio 2011) diff --git a/translations/content/it/errors/null-in-switch.yaml b/translations/content/it/errors/null-in-switch.yaml new file mode 100644 index 0000000..fd716bd --- /dev/null +++ b/translations/content/it/errors/null-in-switch.yaml @@ -0,0 +1,18 @@ +--- +title: Caso null in switch +oldApproach: Guardia prima dello switch +modernApproach: case null +summary: "Gestisci null direttamente come caso di uno switch — nessuna guardia separata necessaria." +explanation: "Lo switch con pattern matching può corrispondere a null come etichetta case. Questo elimina la necessità di un controllo null prima dello switch e rende la gestione del null esplicita e visibile." +whyModernWins: +- icon: 🎯 + title: Esplicito + desc: "La gestione del null è visibile direttamente nello switch." +- icon: 🛡️ + title: Nessuna NPE + desc: "Lo switch su un valore null non lancerà NullPointerException." +- icon: 📐 + title: Tutto-in-uno + desc: "Tutti i casi incluso null in un singolo switch." +support: + description: Ampiamente disponibile dal JDK 21 LTS (settembre 2023) diff --git a/translations/content/it/errors/optional-chaining.yaml b/translations/content/it/errors/optional-chaining.yaml new file mode 100644 index 0000000..f7840f2 --- /dev/null +++ b/translations/content/it/errors/optional-chaining.yaml @@ -0,0 +1,18 @@ +--- +title: Concatenazione Optional +oldApproach: Controlli null annidati +modernApproach: Pipeline Optional +summary: "Sostituisci i controlli null annidati con una pipeline Optional." +explanation: "Optional.map() concatena attraverso valori nullable, cortocircuitando al primo null. orElse() fornisce il default. Questo elimina la piramide della morte nei controlli null." +whyModernWins: +- icon: 🔗 + title: Concatenabile + desc: "Ogni passo .map() gestisce il null in modo trasparente." +- icon: 📖 + title: Flusso lineare + desc: "Leggi da sinistra a destra invece di blocchi if annidati." +- icon: 🛡️ + title: A prova di NPE + desc: "Il null è gestito ad ogni passo — nessun crash possibile." +support: + description: "Disponibile dal JDK 8+ (migliorato in 9+)" diff --git a/translations/content/it/errors/optional-orelsethrow.yaml b/translations/content/it/errors/optional-orelsethrow.yaml new file mode 100644 index 0000000..1d16528 --- /dev/null +++ b/translations/content/it/errors/optional-orelsethrow.yaml @@ -0,0 +1,18 @@ +--- +title: Optional.orElseThrow() senza supplier +oldApproach: get() o orElseThrow(supplier) +modernApproach: orElseThrow() +summary: "Usa Optional.orElseThrow() come alternativa più chiara e rivelante l'intento a get()." +explanation: "Optional.get() è ampiamente considerato un code smell perché nasconde la possibilità di fallimento. Il orElseThrow() senza argomenti, aggiunto in Java 10, fa esattamente la stessa cosa ma rende l'intento esplicito: lo sviluppatore si aspetta un valore e vuole un'eccezione se assente." +whyModernWins: +- icon: 📖 + title: Auto-documentante + desc: "orElseThrow() segnala chiaramente che l'assenza è inaspettata." +- icon: 🔒 + title: Evita get() + desc: "Gli strumenti di analisi statica segnalano get() come rischioso; orElseThrow() è idiomatico." +- icon: ⚡ + title: Meno boilerplate + desc: "Non è necessario passare un supplier per il NoSuchElementException predefinito." +support: + description: "Disponibile dal JDK 10 (marzo 2018)." diff --git a/translations/content/it/errors/record-based-errors.yaml b/translations/content/it/errors/record-based-errors.yaml new file mode 100644 index 0000000..5dd2221 --- /dev/null +++ b/translations/content/it/errors/record-based-errors.yaml @@ -0,0 +1,18 @@ +--- +title: Risposte di errore basate su record +oldApproach: Map o classe verbosa +modernApproach: Record di errore +summary: "Usa i record per tipi di risposta errore concisi e immutabili." +explanation: "I record sono perfetti per le risposte di errore — sono immutabili, hanno equals/hashCode integrati per il confronto e toString per il logging. I costruttori personalizzati aggiungono validazione o valori predefiniti." +whyModernWins: +- icon: 📏 + title: Conciso + desc: "Definisci i tipi di errore in 3 righe invece di 30." +- icon: 🔒 + title: Immutabile + desc: "I dati dell'errore non possono essere modificati accidentalmente dopo la creazione." +- icon: 📋 + title: toString automatico + desc: "Perfetto per il logging — mostra tutti i campi automaticamente." +support: + description: Ampiamente disponibile dal JDK 16 (marzo 2021) diff --git a/translations/content/it/errors/require-nonnull-else.yaml b/translations/content/it/errors/require-nonnull-else.yaml new file mode 100644 index 0000000..b40ce09 --- /dev/null +++ b/translations/content/it/errors/require-nonnull-else.yaml @@ -0,0 +1,18 @@ +--- +title: Objects.requireNonNullElse() +oldApproach: Controllo null ternario +modernApproach: requireNonNullElse() +summary: "Ottieni un valore non-null con un default chiaro, senza ternario." +explanation: "requireNonNullElse restituisce il primo argomento se non-null, altrimenti il secondo. Il default stesso non può essere null — lancia NPE se entrambi sono null, catturando i bug precocemente." +whyModernWins: +- icon: 📖 + title: Intento chiaro + desc: "Il nome del metodo descrive esattamente cosa fa." +- icon: 🛡️ + title: Default null-safe + desc: "Anche il valore di default viene controllato per null." +- icon: 📏 + title: Leggibile + desc: "Meglio del ternario per la semplice logica null-o-default." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/io/deserialization-filters.yaml b/translations/content/it/io/deserialization-filters.yaml new file mode 100644 index 0000000..aba53a7 --- /dev/null +++ b/translations/content/it/io/deserialization-filters.yaml @@ -0,0 +1,18 @@ +--- +title: Filtri di deserializzazione +oldApproach: Accetta tutto +modernApproach: ObjectInputFilter +summary: "Limita le classi che possono essere deserializzate per prevenire gli attacchi." +explanation: "ObjectInputFilter permette di creare allowlist/denylist di classi, limitare la profondità del grafo degli oggetti, le dimensioni degli array e i conteggi dei riferimenti. Difende dalle vulnerabilità di deserializzazione senza librerie esterne." +whyModernWins: +- icon: 🛡️ + title: Sicurezza + desc: "Previene la deserializzazione di classi inaspettate/malevole." +- icon: 📐 + title: Granulare + desc: "Controlla profondità, dimensione array, riferimenti e pattern di classi." +- icon: 🏗️ + title: A livello JVM + desc: "Imposta un filtro globale per tutta la deserializzazione nella JVM." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/io/file-memory-mapping.yaml b/translations/content/it/io/file-memory-mapping.yaml new file mode 100644 index 0000000..5078b83 --- /dev/null +++ b/translations/content/it/io/file-memory-mapping.yaml @@ -0,0 +1,18 @@ +--- +title: Mappatura in memoria di file +oldApproach: MappedByteBuffer +modernApproach: MemorySegment con Arena +summary: "Mappa file più grandi di 2 GB con pulizia deterministica usando MemorySegment." +explanation: "L'API Foreign Function & Memory (JEP 454) introduce MemorySegment per un accesso sicuro ed efficiente alla memoria. A differenza di MappedByteBuffer, MemorySegment supporta file più grandi di 2 GB (Integer.MAX_VALUE), fornisce pulizia deterministica tramite Arena e offre prestazioni migliori con l'hardware moderno." +whyModernWins: +- icon: 📏 + title: Nessun limite di dimensione + desc: "Mappa file più grandi di 2 GB senza workaround." +- icon: 🔒 + title: Pulizia deterministica + desc: "Arena garantisce che la memoria venga liberata all'uscita dello scope, non al momento del GC." +- icon: ⚡ + title: Prestazioni migliori + desc: "Allineato con i moderni modelli di memoria e hardware." +support: + description: "Disponibile dal JDK 22 (marzo 2024)" diff --git a/translations/content/it/io/files-mismatch.yaml b/translations/content/it/io/files-mismatch.yaml new file mode 100644 index 0000000..5437f56 --- /dev/null +++ b/translations/content/it/io/files-mismatch.yaml @@ -0,0 +1,18 @@ +--- +title: Files.mismatch() +oldApproach: Confronto byte per byte manuale +modernApproach: Files.mismatch() +summary: "Confronta due file in modo efficiente senza caricarli in memoria." +explanation: "Files.mismatch() restituisce la posizione del primo byte che differisce, o -1 se i file sono identici. Legge in modo lazy e cortocircuita alla prima differenza." +whyModernWins: +- icon: ⚡ + title: Efficiente in memoria + desc: "Non carica interi file in array di byte." +- icon: 🎯 + title: Individua la differenza + desc: "Restituisce la posizione esatta del primo byte diverso." +- icon: 📏 + title: Una chiamata + desc: "Nessuna logica di confronto array di byte manuale." +support: + description: Ampiamente disponibile dal JDK 12 (marzo 2019) diff --git a/translations/content/it/io/http-client.yaml b/translations/content/it/io/http-client.yaml new file mode 100644 index 0000000..c3bbbeb --- /dev/null +++ b/translations/content/it/io/http-client.yaml @@ -0,0 +1,18 @@ +--- +title: Client HTTP moderno +oldApproach: HttpURLConnection +modernApproach: HttpClient +summary: "Usa l'HttpClient integrato per richieste HTTP pulite e moderne." +explanation: "HttpClient supporta HTTP/1.1 e HTTP/2, richieste asincrone, WebSocket, executor personalizzati e connection pooling. Niente più casting di URLConnection o lettura manuale di InputStream." +whyModernWins: +- icon: 📐 + title: API Builder + desc: "Builder fluente per richieste, header e timeout." +- icon: 🔄 + title: Supporto HTTP/2 + desc: "HTTP/2 integrato con multiplexing e server push." +- icon: ⚡ + title: Pronto per asincrono + desc: "sendAsync() restituisce CompletableFuture." +support: + description: Ampiamente disponibile dal JDK 11 (settembre 2018) diff --git a/translations/content/it/io/inputstream-transferto.yaml b/translations/content/it/io/inputstream-transferto.yaml new file mode 100644 index 0000000..e06eb1b --- /dev/null +++ b/translations/content/it/io/inputstream-transferto.yaml @@ -0,0 +1,18 @@ +--- +title: InputStream.transferTo() +oldApproach: Loop di copia manuale +modernApproach: transferTo() +summary: "Copia un InputStream su un OutputStream in una chiamata." +explanation: "transferTo() legge tutti i byte dal flusso di input e li scrive nel flusso di output. Nessuna gestione del buffer, nessun loop. Usa un buffer interno ottimizzato." +whyModernWins: +- icon: 📏 + title: Una riga + desc: "Sostituisci l'intero loop di lettura/scrittura con una chiamata a metodo." +- icon: ⚡ + title: Ottimizzato + desc: "La dimensione del buffer interno è ottimizzata per le prestazioni." +- icon: 🛡️ + title: Nessun bug + desc: "Nessun errore off-by-one nella gestione del buffer." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/io/io-class-console-io.yaml b/translations/content/it/io/io-class-console-io.yaml new file mode 100644 index 0000000..d5d9970 --- /dev/null +++ b/translations/content/it/io/io-class-console-io.yaml @@ -0,0 +1,18 @@ +--- +title: Classe IO per I/O da console +oldApproach: System.out / Scanner +modernApproach: Classe IO +summary: "La nuova classe IO fornisce metodi semplici e concisi per input e output da console." +explanation: "Java 25 introduce la classe IO (java.io.IO) come parte della funzionalità delle classi dichiarate implicitamente. Fornisce metodi statici come println(), print(), readln() e read() che sostituiscono la verbosa combinazione di System.out e Scanner. IO.readln(prompt) gestisce sia il prompting che la lettura in una singola chiamata. La classe è disponibile automaticamente nei file sorgente compatti e può essere utilizzata nelle classi tradizionali tramite import." +whyModernWins: +- icon: ✨ + title: Molto più semplice + desc: "Due metodi sostituiscono sette righe di setup Scanner, prompting, lettura e pulizia." +- icon: 🔒 + title: Nessuna perdita di risorse + desc: "Nessun Scanner da chiudere — i metodi IO gestiscono internamente le risorse." +- icon: �� + title: Adatto ai principianti + desc: "I nuovi sviluppatori possono fare I/O da console senza imparare Scanner, System.out o le istruzioni import." +support: + description: "Anteprima nel JDK 25 come parte delle classi dichiarate implicitamente (JEP 495)" diff --git a/translations/content/it/io/path-of.yaml b/translations/content/it/io/path-of.yaml new file mode 100644 index 0000000..81c8a6f --- /dev/null +++ b/translations/content/it/io/path-of.yaml @@ -0,0 +1,18 @@ +--- +title: Factory Path.of() +oldApproach: Paths.get() +modernApproach: Path.of() +summary: "Usa Path.of() — il moderno metodo factory sull'interfaccia Path." +explanation: "Path.of() è un metodo factory aggiunto direttamente all'interfaccia Path, sostituendo la classe di utilità Paths separata. È più rilevabile e coerente con List.of(), Map.of(), ecc." +whyModernWins: +- icon: 📐 + title: API coerente + desc: "Segue il pattern factory .of() come List.of(), Set.of()." +- icon: 📖 + title: Rilevabile + desc: "Trovato sul tipo Path stesso, non in una classe Paths separata." +- icon: 🧹 + title: Una classe in meno + desc: "Non è necessario importare la classe di utilità Paths." +support: + description: Ampiamente disponibile dal JDK 11 (settembre 2018) diff --git a/translations/content/it/io/reading-files.yaml b/translations/content/it/io/reading-files.yaml new file mode 100644 index 0000000..5640b7e --- /dev/null +++ b/translations/content/it/io/reading-files.yaml @@ -0,0 +1,18 @@ +--- +title: Lettura di file +oldApproach: BufferedReader +modernApproach: Files.readString() +summary: "Leggi un intero file in una String con una riga." +explanation: "Files.readString() legge l'intero contenuto di un file in una String. Gestisce la codifica (UTF-8 per default) e la pulizia delle risorse. Per file grandi, usa Files.lines() per lo streaming lazy." +whyModernWins: +- icon: 📏 + title: Una riga + desc: "Sostituisci 8 righe di boilerplate BufferedReader." +- icon: 🧹 + title: Pulizia automatica + desc: "Il file handle viene chiuso automaticamente." +- icon: 🌐 + title: UTF-8 per default + desc: "Codifica corretta per default — nessuna confusione di charset." +support: + description: Ampiamente disponibile dal JDK 11 (settembre 2018) diff --git a/translations/content/it/io/try-with-resources-effectively-final.yaml b/translations/content/it/io/try-with-resources-effectively-final.yaml new file mode 100644 index 0000000..e5db21c --- /dev/null +++ b/translations/content/it/io/try-with-resources-effectively-final.yaml @@ -0,0 +1,18 @@ +--- +title: Miglioramento try-with-resources +oldApproach: Ri-dichiarazione variabile +modernApproach: Effettivamente final +summary: "Usa direttamente le variabili effettivamente final nel try-with-resources." +explanation: "Java 9 consente alle variabili effettivamente final di essere usate direttamente nel try-with-resources senza ri-dichiarazione. Questo è più pulito quando la risorsa è stata creata fuori dal blocco try." +whyModernWins: +- icon: 🧹 + title: Nessuna ri-dichiarazione + desc: "Usa direttamente il nome della variabile esistente." +- icon: 📖 + title: Meno confusione + desc: "Nessun nome di variabile separato all'interno del blocco try." +- icon: 📏 + title: Conciso + desc: "Meno righe, stessa sicurezza delle risorse." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/io/writing-files.yaml b/translations/content/it/io/writing-files.yaml new file mode 100644 index 0000000..9628f7f --- /dev/null +++ b/translations/content/it/io/writing-files.yaml @@ -0,0 +1,18 @@ +--- +title: Scrittura di file +oldApproach: FileWriter + BufferedWriter +modernApproach: Files.writeString() +summary: "Scrivi una String su un file con una riga." +explanation: "Files.writeString() scrive il contenuto su un file con codifica UTF-8 per default. È possibile passare opzioni per l'accodamento, la creazione, ecc." +whyModernWins: +- icon: 📏 + title: Una riga + desc: "Nessun wrapping di writer o try-with-resources necessario." +- icon: 🛡️ + title: Default sicuri + desc: "Codifica UTF-8, pulizia corretta del file handle." +- icon: 🔧 + title: Opzioni + desc: "Passa flag OpenOption per accodamento, creazione, ecc." +support: + description: Ampiamente disponibile dal JDK 11 (settembre 2018) diff --git a/translations/content/it/language/compact-canonical-constructor.yaml b/translations/content/it/language/compact-canonical-constructor.yaml new file mode 100644 index 0000000..b93e99c --- /dev/null +++ b/translations/content/it/language/compact-canonical-constructor.yaml @@ -0,0 +1,18 @@ +--- +title: Costruttore canonico compatto +oldApproach: Validazione costruttore esplicita +modernApproach: Costruttore compatto +summary: "Valida e normalizza i campi del record senza ripetere le liste di parametri." +explanation: "I record possono dichiarare un costruttore canonico compatto che omette la lista dei parametri e le assegnazioni dei campi. Il compilatore assegna automaticamente i parametri ai campi dopo l'esecuzione della tua logica di validazione. Ideale per controlli preliminari, copie difensive e normalizzazione." +whyModernWins: +- icon: ✂️ + title: Meno ripetizione + desc: "Non è necessario ripetere la lista dei parametri o assegnare manualmente ogni campo." +- icon: 🛡️ + title: Validazione + desc: "Perfetto per controlli null, validazione degli intervalli e copie difensive." +- icon: 📖 + title: Intento più chiaro + desc: "La sintassi compatta enfatizza la validazione, non il boilerplate." +support: + description: Ampiamente disponibile dal JDK 16 (marzo 2021) diff --git a/translations/content/it/language/compact-source-files.yaml b/translations/content/it/language/compact-source-files.yaml new file mode 100644 index 0000000..4418bde --- /dev/null +++ b/translations/content/it/language/compact-source-files.yaml @@ -0,0 +1,18 @@ +--- +title: File sorgente compatti +oldApproach: Classe main con cerimonia +modernApproach: void main() +summary: "Scrivi un programma completo senza dichiarazione di classe o public static void main." +explanation: "I file sorgente compatti rimuovono la cerimonia delle dichiarazioni di classe e la firma del metodo main per programmi semplici. Combinati con l'importazione implicita di java.io.IO, anche println è disponibile direttamente." +whyModernWins: +- icon: 🚀 + title: Zero cerimonia + desc: "Nessuna classe, nessun public static void main, nessun String[] args." +- icon: 🎓 + title: Adatto ai principianti + desc: "I nuovi programmatori possono scrivere codice utile dalla prima riga." +- icon: 📝 + title: Simile a script + desc: "Perfetto per prototipi veloci, script ed esempi." +support: + description: "Finalizzato nel JDK 25 LTS (JEP 512, settembre 2025)." diff --git a/translations/content/it/language/default-interface-methods.yaml b/translations/content/it/language/default-interface-methods.yaml new file mode 100644 index 0000000..3368a18 --- /dev/null +++ b/translations/content/it/language/default-interface-methods.yaml @@ -0,0 +1,18 @@ +--- +title: Metodi default nelle interfacce +oldApproach: Classi astratte per comportamento condiviso +modernApproach: Metodi default nelle interfacce +summary: "Aggiungi implementazioni di metodi direttamente nelle interfacce, abilitando l'ereditarietà multipla del comportamento." +explanation: "Prima di Java 8, condividere il comportamento tra classi non correlate richiedeva classi astratte, che limitavano all'ereditarietà singola. I metodi default permettono alle interfacce di fornire implementazioni di metodi, così le classi possono ereditare comportamento da più interfacce. Questo è stato essenziale per evolvere le API Collections (es. List.forEach, Map.getOrDefault) senza rompere le implementazioni esistenti." +whyModernWins: +- icon: 🔀 + title: Ereditarietà multipla + desc: "Le classi possono implementare molte interfacce con metodi default, a differenza dell'ereditarietà da una singola classe astratta." +- icon: 📦 + title: Evoluzione dell'API + desc: "Aggiungi nuovi metodi alle interfacce senza rompere le implementazioni esistenti." +- icon: 🧩 + title: Comportamento componibile + desc: "Mescola e abbina le capacità di più interfacce liberamente." +support: + description: "Disponibile dal JDK 8 (marzo 2014)." diff --git a/translations/content/it/language/diamond-operator.yaml b/translations/content/it/language/diamond-operator.yaml new file mode 100644 index 0000000..9d6bcce --- /dev/null +++ b/translations/content/it/language/diamond-operator.yaml @@ -0,0 +1,18 @@ +--- +title: Diamond con classi anonime +oldApproach: Ripeti gli argomenti di tipo +modernApproach: Diamond <> +summary: "L'operatore diamond ora funziona anche con le classi anonime." +explanation: "Java 7 ha introdotto <> ma non funzionava con le classi interne anonime. Java 9 ha corretto questo, quindi non è mai necessario ripetere gli argomenti di tipo sul lato destro." +whyModernWins: +- icon: 📏 + title: Regole coerenti + desc: "Diamond funziona ovunque — costruttori e classi anonime allo stesso modo." +- icon: 🧹 + title: Meno ridondanza + desc: "Gli argomenti di tipo sono indicati una volta a sinistra, mai ripetuti." +- icon: 🔧 + title: Principio DRY + desc: "Il compilatore conosce già il tipo — perché scriverlo due volte?" +support: + description: "Diamond con classi anonime dal JDK 9 (settembre 2017)." diff --git a/translations/content/it/language/exhaustive-switch.yaml b/translations/content/it/language/exhaustive-switch.yaml new file mode 100644 index 0000000..76eb6e2 --- /dev/null +++ b/translations/content/it/language/exhaustive-switch.yaml @@ -0,0 +1,18 @@ +--- +title: Switch esaustivo senza default +oldApproach: Default obbligatorio +modernApproach: Esaustività sealed +summary: "Il compilatore verifica che tutti i sottotipi sealed siano coperti — nessun default necessario." +explanation: "Quando si usa lo switch su un tipo sealed, il compilatore conosce tutti i possibili sottotipi e verifica che ogni caso sia gestito. Se aggiungi un nuovo sottotipo, il compilatore segnala ogni switch ora incompleto." +whyModernWins: +- icon: ✅ + title: Sicurezza in fase di compilazione + desc: "Aggiungi un nuovo sottotipo e il compilatore mostra ogni punto da aggiornare." +- icon: 🚫 + title: Nessun codice morto + desc: "Nessun ramo default irraggiungibile che maschera i bug." +- icon: 📐 + title: Tipi algebrici + desc: "Sealed + record + switch esaustivo = ADT propri in Java." +support: + description: Ampiamente disponibile dal JDK 21 LTS (settembre 2023) diff --git a/translations/content/it/language/flexible-constructor-bodies.yaml b/translations/content/it/language/flexible-constructor-bodies.yaml new file mode 100644 index 0000000..2603c0d --- /dev/null +++ b/translations/content/it/language/flexible-constructor-bodies.yaml @@ -0,0 +1,18 @@ +--- +title: Corpi di costruttore flessibili +oldApproach: Valida dopo super() +modernApproach: Codice prima di super() +summary: "Valida e calcola valori prima di chiamare super() o this()." +explanation: "Java 25 rimuove la restrizione che super() debba essere la prima istruzione. Ora puoi validare argomenti, calcolare valori derivati e preparare lo stato prima di delegare al costruttore padre." +whyModernWins: +- icon: 🛡️ + title: Fail fast + desc: "Valida gli argomenti prima che il costruttore della superclasse venga eseguito." +- icon: 🧮 + title: Calcola prima + desc: "Deriva valori e prepara i dati prima di chiamare super()." +- icon: 🧹 + title: Nessun workaround + desc: "Niente più metodi helper statici o factory pattern per aggirare la restrizione." +support: + description: "Finalizzato nel JDK 25 LTS (JEP 513, settembre 2025)." diff --git a/translations/content/it/language/guarded-patterns.yaml b/translations/content/it/language/guarded-patterns.yaml new file mode 100644 index 0000000..598629c --- /dev/null +++ b/translations/content/it/language/guarded-patterns.yaml @@ -0,0 +1,18 @@ +--- +title: Pattern con guardia tramite when +oldApproach: if annidato +modernApproach: Clausola when +summary: "Aggiungi condizioni ai case del pattern usando le guardie when." +explanation: "I pattern con guardia permettono di affinare una corrispondenza di tipo con una condizione booleana aggiuntiva. Questo mantiene tutta la logica di branching nello switch invece di annidare istruzioni if all'interno dei case." +whyModernWins: +- icon: 🎯 + title: Corrispondenza precisa + desc: "Combina tipo + condizione in un'unica etichetta case." +- icon: 📐 + title: Struttura piatta + desc: "Nessun if/else annidato all'interno dei case dello switch." +- icon: 📖 + title: Intento leggibile + desc: "La clausola when si legge come linguaggio naturale." +support: + description: Ampiamente disponibile dal JDK 21 LTS (settembre 2023) diff --git a/translations/content/it/language/markdown-javadoc-comments.yaml b/translations/content/it/language/markdown-javadoc-comments.yaml new file mode 100644 index 0000000..85ddbc8 --- /dev/null +++ b/translations/content/it/language/markdown-javadoc-comments.yaml @@ -0,0 +1,18 @@ +--- +title: Markdown nei commenti Javadoc +oldApproach: Javadoc basato su HTML +modernApproach: Javadoc Markdown +summary: "Scrivi commenti Javadoc in Markdown invece di HTML per una migliore leggibilità." +explanation: "Java 23 introduce i commenti Javadoc in stile Markdown con /// come alternativa al formato tradizionale /** */ basato su HTML. La sintassi Markdown è più naturale da scrivere e leggere, con supporto per blocchi di codice, enfasi, liste e link. Il compilatore converte il Markdown in HTML per l'output javadoc." +whyModernWins: +- icon: 📖 + title: Sintassi naturale + desc: "Usa i backtick per il codice inline e ``` per i blocchi invece dei tag HTML." +- icon: ✍️ + title: Più facile da scrivere + desc: "Nessun bisogno di {@code},
, tag 

— scrivi semplicemente Markdown." +- icon: 👁 + title: Migliore negli editor + desc: "Il Markdown viene renderizzato splendidamente nei moderni IDE e editor di testo." +support: + description: "Disponibile dal JDK 23 (settembre 2024)" diff --git a/translations/content/it/language/module-import-declarations.yaml b/translations/content/it/language/module-import-declarations.yaml new file mode 100644 index 0000000..ac1248b --- /dev/null +++ b/translations/content/it/language/module-import-declarations.yaml @@ -0,0 +1,18 @@ +--- +title: Dichiarazioni di importazione modulo +oldApproach: Molte importazioni +modernApproach: import module +summary: "Importa tutti i package esportati da un modulo con una singola dichiarazione." +explanation: "Le dichiarazioni di importazione modulo permettono di importare tutto ciò che un modulo esporta con una riga. Particolarmente utile per java.base che copre collezioni, I/O, stream e altro." +whyModernWins: +- icon: 🧹 + title: Una riga + desc: "Sostituisci un muro di importazioni con una singola importazione modulo." +- icon: 📦 + title: Consapevole dei moduli + desc: "Sfrutta il sistema di moduli per importare insiemi coerenti di package." +- icon: 🚀 + title: Avvio rapido + desc: "Perfetto per script e prototipi dove le liste di importazioni sono noiose." +support: + description: "Finalizzato nel JDK 25 LTS (JEP 511, settembre 2025)." diff --git a/translations/content/it/language/pattern-matching-instanceof.yaml b/translations/content/it/language/pattern-matching-instanceof.yaml new file mode 100644 index 0000000..56316e7 --- /dev/null +++ b/translations/content/it/language/pattern-matching-instanceof.yaml @@ -0,0 +1,18 @@ +--- +title: Pattern matching per instanceof +oldApproach: instanceof + Cast +modernApproach: Variabile pattern +summary: "Combina il controllo del tipo e il cast in un unico passo con il pattern matching." +explanation: "Il pattern matching per instanceof elimina il cast ridondante dopo un controllo del tipo. La variabile è automaticamente scoped dove il pattern corrisponde, rendendo il codice più sicuro e conciso." +whyModernWins: +- icon: 🔄 + title: Nessun cast ridondante + desc: "Il controllo del tipo e il binding della variabile avvengono in un'unica espressione." +- icon: 📏 + title: Meno righe + desc: "Una riga invece di due — la riga del cast sparisce completamente." +- icon: 🛡️ + title: Scope sicuro + desc: "La variabile pattern è nello scope solo dove il tipo è garantito." +support: + description: Ampiamente disponibile dal JDK 16 (marzo 2021) diff --git a/translations/content/it/language/pattern-matching-switch.yaml b/translations/content/it/language/pattern-matching-switch.yaml new file mode 100644 index 0000000..be48672 --- /dev/null +++ b/translations/content/it/language/pattern-matching-switch.yaml @@ -0,0 +1,18 @@ +--- +title: Pattern matching in switch +oldApproach: Catena if-else +modernApproach: Pattern di tipo +summary: "Sostituisci le catene if-else instanceof con pattern di tipo switch puliti." +explanation: "Il pattern matching in switch permette di corrispondere direttamente sui tipi, combinando il test del tipo, il cast e il binding in un'unica etichetta case concisa. Il compilatore verifica la completezza." +whyModernWins: +- icon: 📐 + title: Dispatch strutturato + desc: "Lo switch rende la struttura di branching esplicita e scansionabile." +- icon: 🎯 + title: Forma espressione + desc: "Restituisce un valore direttamente — nessuna variabile mutabile necessaria." +- icon: ✅ + title: Esaustività + desc: "Il compilatore verifica che tutti i tipi siano gestiti." +support: + description: Ampiamente disponibile dal JDK 21 LTS (settembre 2023) diff --git a/translations/content/it/language/primitive-types-in-patterns.yaml b/translations/content/it/language/primitive-types-in-patterns.yaml new file mode 100644 index 0000000..7b9ff35 --- /dev/null +++ b/translations/content/it/language/primitive-types-in-patterns.yaml @@ -0,0 +1,18 @@ +--- +title: Tipi primitivi nei pattern +oldApproach: Controlli manuali degli intervalli +modernApproach: Pattern primitivi +summary: "Il pattern matching ora funziona anche con i tipi primitivi, non solo gli oggetti." +explanation: "Java 25 estende il pattern matching ai tipi primitivi. Puoi usare int, long, double ecc. nei pattern switch con guardie when, eliminando la necessità di boxing o controlli manuali degli intervalli." +whyModernWins: +- icon: 📦 + title: Nessun boxing + desc: "Corrisponde ai primitivi direttamente — nessun wrapper Integer necessario." +- icon: 🎯 + title: Coerenza dei pattern + desc: "Stessa sintassi dei pattern per oggetti e primitivi." +- icon: ⚡ + title: Prestazioni migliori + desc: "Evita l'overhead dell'autoboxing nel pattern matching." +support: + description: "Anteprima nel JDK 25 (terza anteprima, JEP 507). Richiede --enable-preview." diff --git a/translations/content/it/language/private-interface-methods.yaml b/translations/content/it/language/private-interface-methods.yaml new file mode 100644 index 0000000..278c871 --- /dev/null +++ b/translations/content/it/language/private-interface-methods.yaml @@ -0,0 +1,18 @@ +--- +title: Metodi privati nelle interfacce +oldApproach: Logica duplicata +modernApproach: Metodi privati +summary: "Estrai la logica condivisa nelle interfacce usando metodi privati." +explanation: "Java 9 consente i metodi privati nelle interfacce, permettendo di condividere codice tra i metodi default senza esporre i dettagli di implementazione alle classi implementanti." +whyModernWins: +- icon: 🧩 + title: Riutilizzo del codice + desc: "Condividi la logica tra i metodi default senza duplicazione." +- icon: 🔐 + title: Incapsulamento + desc: "I dettagli di implementazione rimangono nascosti alle classi implementanti." +- icon: 🧹 + title: Interfacce DRY + desc: "Niente più copia-incolla tra i metodi default." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/language/record-patterns.yaml b/translations/content/it/language/record-patterns.yaml new file mode 100644 index 0000000..1a9ed83 --- /dev/null +++ b/translations/content/it/language/record-patterns.yaml @@ -0,0 +1,18 @@ +--- +title: Pattern record (destrutturazione) +oldApproach: Accesso manuale +modernApproach: Destrutturazione +summary: "Destruttua i record direttamente nei pattern — estrai i campi in un unico passo." +explanation: "I pattern record permettono di decomporre i componenti di un record direttamente in instanceof e switch. Sono supportati anche i pattern annidati, abilitando il matching profondo senza variabili intermedie." +whyModernWins: +- icon: 🎯 + title: Estrazione diretta + desc: "Accedi ai componenti del record senza chiamare manualmente gli accessori." +- icon: 🪆 + title: Annidabile + desc: "I pattern possono annidarsi — corrisponde ai record interni in un'unica espressione." +- icon: 📏 + title: Codice compatto + desc: "Cinque righe diventano due — meno cerimonia, stessa chiarezza." +support: + description: Ampiamente disponibile dal JDK 21 LTS (settembre 2023) diff --git a/translations/content/it/language/records-for-data-classes.yaml b/translations/content/it/language/records-for-data-classes.yaml new file mode 100644 index 0000000..81b2261 --- /dev/null +++ b/translations/content/it/language/records-for-data-classes.yaml @@ -0,0 +1,18 @@ +--- +title: Record per classi di dati +oldApproach: POJO verboso +modernApproach: record +summary: "Una riga sostituisce oltre 30 righe di codice boilerplate per i data carrier immutabili." +explanation: "I record generano automaticamente il costruttore, gli accessori (x(), y()), equals(), hashCode() e toString(). Sono immutabili per design e ideali per DTO, value object e pattern matching." +whyModernWins: +- icon: ⚡ + title: Definizione in una riga + desc: "Una singola riga sostituisce costruttore, getter, equals, hashCode, toString." +- icon: 🔒 + title: Immutabile per default + desc: "Tutti i campi sono final — nessun setter pericoloso." +- icon: 🧩 + title: Pattern-friendly + desc: "I record funzionano con i pattern di destrutturazione in switch e instanceof." +support: + description: Ampiamente disponibile dal JDK 16 (marzo 2021) diff --git a/translations/content/it/language/sealed-classes.yaml b/translations/content/it/language/sealed-classes.yaml new file mode 100644 index 0000000..cc5f5ac --- /dev/null +++ b/translations/content/it/language/sealed-classes.yaml @@ -0,0 +1,18 @@ +--- +title: Classi sealed per gerarchie di tipi +oldApproach: Gerarchia aperta +modernApproach: sealed permits +summary: "Limita le classi che possono estendere un tipo — abilitando switch esaustivi." +explanation: "Le classi sealed definiscono un insieme chiuso di sottotipi. Il compilatore conosce tutti i casi possibili, abilitando il pattern matching esaustivo senza un ramo default. Combinate con i record, modellano i tipi di dati algebrici." +whyModernWins: +- icon: 🔐 + title: Gerarchia controllata + desc: "Solo i sottotipi consentiti possono estendere — nessuna sottoclasse a sorpresa." +- icon: ✅ + title: Matching esaustivo + desc: "Il compilatore verifica che lo switch copra tutti i casi, senza default necessario." +- icon: 📐 + title: Tipi di dati algebrici + desc: "Modella i tipi somma in modo naturale — sealed + record = ADT in Java." +support: + description: Ampiamente disponibile dal JDK 17 LTS (settembre 2021) diff --git a/translations/content/it/language/static-members-in-inner-classes.yaml b/translations/content/it/language/static-members-in-inner-classes.yaml new file mode 100644 index 0000000..bf66106 --- /dev/null +++ b/translations/content/it/language/static-members-in-inner-classes.yaml @@ -0,0 +1,18 @@ +--- +title: Membri statici nelle classi interne +oldApproach: Necessaria la classe nested statica +modernApproach: Membri statici nelle classi interne +summary: "Definisci membri statici nelle classi interne senza richiedere classi nested statiche." +explanation: "Prima di Java 16, solo le classi nested statiche potevano contenere membri statici. Le classi interne (non statiche) non potevano avere statici perché richiedevano un'istanza di enclosing. Java 16 allenta questa restrizione, permettendo campi statici, metodi e anche tipi nested nelle classi interne." +whyModernWins: +- icon: 🔓 + title: Più flessibilità + desc: "Le classi interne ora possono avere membri statici quando necessario." +- icon: 🧩 + title: Stato condiviso + desc: "Traccia lo stato condiviso tra le istanze di una classe interna." +- icon: 📐 + title: Libertà di design + desc: "Non è necessario promuovere a classe nested statica solo per un campo statico." +support: + description: Ampiamente disponibile dal JDK 16 (marzo 2021) diff --git a/translations/content/it/language/static-methods-in-interfaces.yaml b/translations/content/it/language/static-methods-in-interfaces.yaml new file mode 100644 index 0000000..7f73487 --- /dev/null +++ b/translations/content/it/language/static-methods-in-interfaces.yaml @@ -0,0 +1,18 @@ +--- +title: Metodi statici nelle interfacce +oldApproach: Classi di utilità +modernApproach: Metodi statici nelle interfacce +summary: "Aggiungi metodi di utilità statici direttamente nelle interfacce invece di classi di utilità separate." +explanation: "Prima di Java 8, i metodi di utilità correlati a un'interfaccia dovevano trovarsi in una classe separata (es. Collections per Collection). I metodi statici nelle interfacce permettono di tenere le utilità correlate insieme. Comune nelle API moderne come Comparator.comparing(), Stream.of() e List.of()." +whyModernWins: +- icon: 📦 + title: Migliore organizzazione + desc: "Tieni le utilità correlate con l'interfaccia, non in una classe separata." +- icon: 🔍 + title: Rilevabilità + desc: "I metodi factory e helper si trovano dove te li aspetti." +- icon: 🧩 + title: Coesione dell'API + desc: "Nessun bisogno di classi *Utils o *Helper separate." +support: + description: "Disponibile dal JDK 8 (marzo 2014)" diff --git a/translations/content/it/language/switch-expressions.yaml b/translations/content/it/language/switch-expressions.yaml new file mode 100644 index 0000000..4ae3ec4 --- /dev/null +++ b/translations/content/it/language/switch-expressions.yaml @@ -0,0 +1,18 @@ +--- +title: Espressioni switch +oldApproach: Istruzione switch +modernApproach: Espressione switch +summary: "Switch come espressione che restituisce un valore — niente break, niente fall-through." +explanation: "Le espressioni switch restituiscono un valore direttamente, usano la sintassi a freccia per prevenire i bug da fall-through, e il compilatore verifica l'esaustività. Questo sostituisce la forma a istruzione soggetta a errori." +whyModernWins: +- icon: 🎯 + title: Restituisce un valore + desc: "Assegna direttamente il risultato dello switch — nessuna variabile temporanea necessaria." +- icon: 🛡️ + title: Nessun fall-through + desc: "La sintassi a freccia elimina i bug da fall-through accidentale per break mancanti." +- icon: ✅ + title: Verifica di esaustività + desc: "Il compilatore verifica che tutti i casi siano coperti." +support: + description: Ampiamente disponibile dal JDK 14 (marzo 2020) diff --git a/translations/content/it/language/text-blocks-for-multiline-strings.yaml b/translations/content/it/language/text-blocks-for-multiline-strings.yaml new file mode 100644 index 0000000..3c6825a --- /dev/null +++ b/translations/content/it/language/text-blocks-for-multiline-strings.yaml @@ -0,0 +1,18 @@ +--- +title: Text block per stringhe multiriga +oldApproach: Concatenazione di stringhe +modernApproach: Text Block +summary: "Scrivi stringhe multiriga in modo naturale con i text block delimitati da triple virgolette." +explanation: "I text block permettono di scrivere stringhe multiriga esattamente come appaiono. Non serve più eseguire l'escape delle virgolette o aggiungere \n. Il compilatore rimuove automaticamente l'indentazione superflua." +whyModernWins: +- icon: 📖 + title: Leggibile com'è + desc: "JSON, SQL e HTML appaiono come vero JSON, SQL e HTML nel codice sorgente." +- icon: 🚫 + title: Nessun escape infernale + desc: "Le virgolette incorporate non richiedono il backslash di escape." +- icon: 📐 + title: Indentazione intelligente + desc: "Gli spazi iniziali vengono rimossi automaticamente in base alla posizione del delimitatore di chiusura." +support: + description: Ampiamente disponibile dal JDK 15 (settembre 2020) diff --git a/translations/content/it/language/type-inference-with-var.yaml b/translations/content/it/language/type-inference-with-var.yaml new file mode 100644 index 0000000..9ec63a7 --- /dev/null +++ b/translations/content/it/language/type-inference-with-var.yaml @@ -0,0 +1,18 @@ +--- +title: Inferenza di tipo con var +oldApproach: Tipi espliciti +modernApproach: Parola chiave var +summary: "Usa var per l'inferenza di tipo nelle variabili locali — meno rumore, stessa sicurezza." +explanation: "Da Java 10, il compilatore inferisce i tipi delle variabili locali dal lato destro dell'assegnazione. Questo riduce il rumore visivo senza sacrificare la sicurezza dei tipi. Usa var quando il tipo è ovvio dal contesto." +whyModernWins: +- icon: ⚡ + title: Meno codice ripetitivo + desc: "Non è necessario ripetere tipi generici complessi su entrambi i lati dell'assegnazione." +- icon: 👁 + title: Migliore leggibilità + desc: "Concentrati sui nomi delle variabili e i valori, non sulle dichiarazioni di tipo." +- icon: 🔒 + title: Ancora type-safe + desc: Il compilatore inferisce e applica il tipo esatto in fase di compilazione. +support: + description: Ampiamente disponibile dal JDK 10 (marzo 2018) diff --git a/translations/content/it/language/unnamed-variables.yaml b/translations/content/it/language/unnamed-variables.yaml new file mode 100644 index 0000000..ceabfc6 --- /dev/null +++ b/translations/content/it/language/unnamed-variables.yaml @@ -0,0 +1,18 @@ +--- +title: Variabili senza nome con _ +oldApproach: Variabile non utilizzata +modernApproach: Segnaposto _ +summary: "Usa _ per segnalare l'intento quando una variabile è intenzionalmente non utilizzata." +explanation: "Le variabili senza nome comunicano a lettori e strumenti che un valore viene deliberatamente ignorato. Niente più convenzioni di naming come 'ignored' o 'unused', niente più avvisi IDE." +whyModernWins: +- icon: 📢 + title: Intento chiaro + desc: "_ dice esplicitamente 'questo valore non è necessario qui'." +- icon: 🔇 + title: Nessun avviso + desc: "IDE e linter non segnaleranno variabili intenzionalmente non utilizzate." +- icon: 🧹 + title: Lambda più pulite + desc: "Le lambda multi-parametro sono più pulite quando si usano solo alcuni parametri." +support: + description: "Finalizzato nel JDK 22 (JEP 456, marzo 2024)." diff --git a/translations/content/it/security/key-derivation-functions.yaml b/translations/content/it/security/key-derivation-functions.yaml new file mode 100644 index 0000000..b455b4d --- /dev/null +++ b/translations/content/it/security/key-derivation-functions.yaml @@ -0,0 +1,18 @@ +--- +title: Funzioni di derivazione delle chiavi +oldApproach: PBKDF2 manuale +modernApproach: API KDF +summary: "Deriva chiavi crittografiche usando l'API KDF standard." +explanation: "L'API KDF fornisce un'interfaccia standard per le funzioni di derivazione delle chiavi incluso HKDF. Sostituisce il goffo pattern SecretKeyFactory + PBEKeySpec con una pulita API builder." +whyModernWins: +- icon: 📐 + title: API pulita + desc: "Pattern builder invece degli goffi costruttori KeySpec." +- icon: 🔧 + title: Supporto HKDF + desc: "Algoritmo HKDF moderno insieme a PBKDF2." +- icon: 🛡️ + title: Standard + desc: "API unificata per tutti gli algoritmi di derivazione delle chiavi." +support: + description: "Finalizzato nel JDK 25 LTS (JEP 510, settembre 2025)." diff --git a/translations/content/it/security/pem-encoding.yaml b/translations/content/it/security/pem-encoding.yaml new file mode 100644 index 0000000..ebe0480 --- /dev/null +++ b/translations/content/it/security/pem-encoding.yaml @@ -0,0 +1,18 @@ +--- +title: Codifica/decodifica PEM +oldApproach: Base64 manuale + Header +modernApproach: API PEM +summary: "Codifica e decodifica oggetti crittografici in formato PEM in modo nativo." +explanation: "L'API PEM fornisce codifica/decodifica standard per certificati, chiavi e altri oggetti crittografici in formato PEM. Niente più wrapping Base64 manuale con header BEGIN/END." +whyModernWins: +- icon: 🧹 + title: Nessun Base64 manuale + desc: "Header PEM, wrapping di riga e Base64 gestiti automaticamente." +- icon: 🔄 + title: Bidirezionale + desc: "Codifica in PEM e decodifica da PEM con un'unica API." +- icon: 🛡️ + title: Formato standard + desc: "Produce output PEM conforme a RFC 7468." +support: + description: "Anteprima nel JDK 25 (JEP 470). Richiede --enable-preview." diff --git a/translations/content/it/security/random-generator.yaml b/translations/content/it/security/random-generator.yaml new file mode 100644 index 0000000..a4c5013 --- /dev/null +++ b/translations/content/it/security/random-generator.yaml @@ -0,0 +1,18 @@ +--- +title: Interfaccia RandomGenerator +oldApproach: new Random() / ThreadLocalRandom +modernApproach: Factory RandomGenerator +summary: "Usa l'interfaccia RandomGenerator per scegliere gli algoritmi di numeri casuali per nome senza accoppiamento a una classe specifica." +explanation: "JDK 17 ha introdotto RandomGenerator come interfaccia comune per tutte le implementazioni RNG. Invece di codificare direttamente new Random() o ThreadLocalRandom, puoi selezionare gli algoritmi per nome tramite una factory, rendendo facile passare tra algoritmi ottimizzati per diversi casi d'uso (velocità, qualità statistica, divisibilità)." +whyModernWins: +- icon: 🔧 + title: Algoritmo-agnostico + desc: "Scegli il miglior algoritmo RNG per nome senza cambiare la struttura del codice." +- icon: ⚡ + title: Algoritmi migliori + desc: "Accesso ai moderni generatori LXM con proprietà statistiche superiori." +- icon: 🔗 + title: API unificata + desc: "Un'interfaccia copre Random, ThreadLocalRandom, SplittableRandom e altro." +support: + description: "Disponibile dal JDK 17 (settembre 2021, JEP 356)." diff --git a/translations/content/it/security/strong-random.yaml b/translations/content/it/security/strong-random.yaml new file mode 100644 index 0000000..c1aa0a2 --- /dev/null +++ b/translations/content/it/security/strong-random.yaml @@ -0,0 +1,18 @@ +--- +title: Generazione di numeri casuali sicuri +oldApproach: new SecureRandom() +modernApproach: getInstanceStrong() +summary: "Ottieni l'implementazione SecureRandom più forte della piattaforma." +explanation: "getInstanceStrong() restituisce l'implementazione SecureRandom configurata come la più forte sulla piattaforma. Questo è controllato dalla proprietà di sicurezza securerandom.strongAlgorithms." +whyModernWins: +- icon: 🛡️ + title: La più forte disponibile + desc: "Seleziona automaticamente il miglior algoritmo per la piattaforma." +- icon: 📖 + title: Intento esplicito + desc: "Comunica chiaramente che è richiesta la casualità forte." +- icon: 🔧 + title: Configurabile + desc: "Gli amministratori possono cambiare l'algoritmo forte tramite le proprietà di sicurezza." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/security/tls-default.yaml b/translations/content/it/security/tls-default.yaml new file mode 100644 index 0000000..c70cc9c --- /dev/null +++ b/translations/content/it/security/tls-default.yaml @@ -0,0 +1,18 @@ +--- +title: TLS 1.3 per default +oldApproach: Configurazione TLS manuale +modernApproach: TLS 1.3 predefinito +summary: "TLS 1.3 è abilitato per default — nessuna configurazione esplicita del protocollo necessaria." +explanation: "Java 11 ha aggiunto il supporto TLS 1.3 e lo ha reso il protocollo preferito. HttpClient lo usa automaticamente. Niente più specifiche manuali delle versioni del protocollo per le connessioni sicure." +whyModernWins: +- icon: 🛡️ + title: Più sicuro + desc: "TLS 1.3 rimuove le suite di cifratura obsolete e i pattern di handshake." +- icon: ⚡ + title: Handshake più veloce + desc: "TLS 1.3 completa in un round trip invece di due." +- icon: 🆓 + title: Zero configurazione + desc: "Sicuro per default — nessuna selezione esplicita del protocollo necessaria." +support: + description: Ampiamente disponibile dal JDK 11 (settembre 2018) diff --git a/translations/content/it/streams/collectors-flatmapping.yaml b/translations/content/it/streams/collectors-flatmapping.yaml new file mode 100644 index 0000000..6428dcf --- /dev/null +++ b/translations/content/it/streams/collectors-flatmapping.yaml @@ -0,0 +1,18 @@ +--- +title: Collectors.flatMapping() +oldApproach: flatMap annidato +modernApproach: flatMapping() +summary: "Usa flatMapping() per appiattire all'interno di un collector di raggruppamento." +explanation: "Collectors.flatMapping() applica una mappatura uno-a-molti come collector downstream. È l'equivalente collector di Stream.flatMap() — utile all'interno di groupingBy o partitioningBy." +whyModernWins: +- icon: 🧩 + title: Componibile + desc: "Funziona come collector downstream all'interno di groupingBy." +- icon: 📐 + title: Un passaggio + desc: "Appiattisci e raggruppa in un'unica traversata dello stream." +- icon: 🔗 + title: Annidabile + desc: "Combina con altri collector downstream." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/streams/optional-ifpresentorelse.yaml b/translations/content/it/streams/optional-ifpresentorelse.yaml new file mode 100644 index 0000000..5f04bc4 --- /dev/null +++ b/translations/content/it/streams/optional-ifpresentorelse.yaml @@ -0,0 +1,18 @@ +--- +title: Optional.ifPresentOrElse() +oldApproach: if/else su Optional +modernApproach: ifPresentOrElse() +summary: "Gestisci entrambi i casi di Optional presente e vuoto in una chiamata." +explanation: "ifPresentOrElse() accetta un Consumer per il caso presente e un Runnable per il caso vuoto. Evita l'anti-pattern isPresent/get." +whyModernWins: +- icon: 📏 + title: Espressione singola + desc: "Entrambi i casi gestiti in una singola chiamata a metodo." +- icon: 🚫 + title: Nessun get() + desc: "Elimina il pericoloso pattern isPresent() + get()." +- icon: 🔗 + title: Fluente + desc: "Si concatena naturalmente dopo findUser() o qualsiasi metodo che restituisce Optional." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/streams/optional-or.yaml b/translations/content/it/streams/optional-or.yaml new file mode 100644 index 0000000..2688d06 --- /dev/null +++ b/translations/content/it/streams/optional-or.yaml @@ -0,0 +1,18 @@ +--- +title: Fallback Optional.or() +oldApproach: Fallback annidato +modernApproach: Catena .or() +summary: "Concatena i fallback Optional senza controlli annidati." +explanation: "Optional.or() restituisce l'Optional originale se ha un valore, altrimenti valuta il supplier per ottenere un Optional alternativo. I supplier sono lazy — chiamati solo quando necessario." +whyModernWins: +- icon: 🔗 + title: Concatenabile + desc: "Impila i fallback in una pipeline leggibile." +- icon: ⚡ + title: Valutazione lazy + desc: "I supplier di fallback vengono eseguiti solo se necessario." +- icon: 📖 + title: Dichiarativo + desc: "Si legge come 'prova il primario, o il secondario, o i default'." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/streams/predicate-not.yaml b/translations/content/it/streams/predicate-not.yaml new file mode 100644 index 0000000..9c614c4 --- /dev/null +++ b/translations/content/it/streams/predicate-not.yaml @@ -0,0 +1,18 @@ +--- +title: Predicate.not() per la negazione +oldApproach: Negazione lambda +modernApproach: Predicate.not() +summary: "Usa Predicate.not() per negare i riferimenti a metodo in modo pulito invece di scrivere wrapper lambda." +explanation: "Prima di Java 11, negare un riferimento a metodo richiedeva di avvolgerlo in una lambda. Predicate.not() permette di negare qualsiasi predicato direttamente, mantenendo il codice leggibile e coerente con lo stile dei riferimenti a metodo in tutta la pipeline stream." +whyModernWins: +- icon: 👁 + title: Negazione più pulita + desc: "Non è necessario avvolgere i riferimenti a metodo in lambda solo per negarli." +- icon: 🔗 + title: Componibile + desc: "Funziona con qualsiasi Predicate, abilitando catene di predicati pulite." +- icon: 📖 + title: Lettura naturale + desc: "Predicate.not(String::isBlank) si legge come in inglese." +support: + description: "Disponibile dal JDK 11 (settembre 2018)." diff --git a/translations/content/it/streams/stream-gatherers.yaml b/translations/content/it/streams/stream-gatherers.yaml new file mode 100644 index 0000000..d932bc1 --- /dev/null +++ b/translations/content/it/streams/stream-gatherers.yaml @@ -0,0 +1,18 @@ +--- +title: Stream gatherer +oldApproach: Collector personalizzato +modernApproach: gather() +summary: "Usa i gatherer per operazioni stream intermedie personalizzate." +explanation: "I gatherer sono una nuova operazione stream intermedia che può esprimere trasformazioni complesse come finestre scorrevoli, gruppi di dimensioni fisse e operazioni di scansione che erano impossibili con le operazioni stream standard." +whyModernWins: +- icon: 🧩 + title: Componibile + desc: "I gatherer si compongono con altre operazioni stream." +- icon: 📦 + title: Operazioni integrate + desc: "windowFixed, windowSliding, fold, scan pronti all'uso." +- icon: 🔧 + title: Estensibile + desc: "Scrivi gatherer personalizzati per qualsiasi trasformazione intermedia." +support: + description: "Finalizzato nel JDK 24 (JEP 485, marzo 2025)." diff --git a/translations/content/it/streams/stream-iterate-predicate.yaml b/translations/content/it/streams/stream-iterate-predicate.yaml new file mode 100644 index 0000000..f3cd9ea --- /dev/null +++ b/translations/content/it/streams/stream-iterate-predicate.yaml @@ -0,0 +1,18 @@ +--- +title: Stream.iterate() con predicato +oldApproach: iterate + limit +modernApproach: iterate(seed, pred, op) +summary: "Usa un predicato per fermare l'iterazione — come un ciclo for in forma stream." +explanation: "Il tre-argomenti Stream.iterate(seed, hasNext, next) funziona come un ciclo for: seed è l'inizio, hasNext determina quando fermarsi e next produce il valore successivo." +whyModernWins: +- icon: 🎯 + title: Terminazione naturale + desc: "Fermati in base a una condizione, non a un limite arbitrario." +- icon: 📐 + title: Equivalente al ciclo for + desc: "Stessa semantica di for(seed; hasNext; next)." +- icon: 🛡️ + title: Nessun rischio di stream infinito + desc: "Il predicato garantisce la terminazione." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/streams/stream-mapmulti.yaml b/translations/content/it/streams/stream-mapmulti.yaml new file mode 100644 index 0000000..861870f --- /dev/null +++ b/translations/content/it/streams/stream-mapmulti.yaml @@ -0,0 +1,18 @@ +--- +title: Stream.mapMulti() +oldApproach: flatMap + List +modernApproach: mapMulti() +summary: "Emetti zero o più elementi per input senza creare stream intermedi." +explanation: "mapMulti() è un'alternativa imperativa a flatMap che evita la creazione di oggetti Stream intermedi per ogni elemento. È più efficiente quando la mappatura produce un numero ridotto di elementi." +whyModernWins: +- icon: ⚡ + title: Meno allocazione + desc: "Nessuno Stream intermedio creato per elemento." +- icon: 🎯 + title: Stile imperativo + desc: "Usa loop e condizionali direttamente." +- icon: 📐 + title: Flessibile + desc: "Emetti zero, uno o molti elementi con pieno controllo." +support: + description: Ampiamente disponibile dal JDK 16 (marzo 2021) diff --git a/translations/content/it/streams/stream-of-nullable.yaml b/translations/content/it/streams/stream-of-nullable.yaml new file mode 100644 index 0000000..37333b1 --- /dev/null +++ b/translations/content/it/streams/stream-of-nullable.yaml @@ -0,0 +1,18 @@ +--- +title: Stream.ofNullable() +oldApproach: Controllo null +modernApproach: ofNullable() +summary: "Crea uno stream da zero o un elemento da un valore nullable." +explanation: "Stream.ofNullable() restituisce uno stream a elemento singolo se il valore è non-null, o uno stream vuoto se null. Elimina il pattern di controllo null ternario." +whyModernWins: +- icon: 📏 + title: Conciso + desc: "Una chiamata sostituisce il condizionale ternario." +- icon: 🔗 + title: Adatto a flatMap + desc: "Perfetto all'interno di flatMap per saltare i valori null." +- icon: 🛡️ + title: Null-safe + desc: "Nessun rischio NPE — null diventa stream vuoto." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/streams/stream-takewhile-dropwhile.yaml b/translations/content/it/streams/stream-takewhile-dropwhile.yaml new file mode 100644 index 0000000..22625fa --- /dev/null +++ b/translations/content/it/streams/stream-takewhile-dropwhile.yaml @@ -0,0 +1,18 @@ +--- +title: Stream takeWhile / dropWhile +oldApproach: Loop manuale +modernApproach: takeWhile/dropWhile +summary: "Prendi o scarta elementi da uno stream in base a un predicato." +explanation: "takeWhile() restituisce elementi finché il predicato è vero e si ferma al primo falso. dropWhile() salta gli elementi finché è vero e restituisce il resto. Entrambi funzionano meglio su stream ordinati." +whyModernWins: +- icon: 🎯 + title: Cortocircuito + desc: "Smette di elaborare non appena il predicato fallisce." +- icon: 🔗 + title: Adatto alla pipeline + desc: "Si concatena naturalmente con altre operazioni stream." +- icon: 📖 + title: Dichiarativo + desc: "takeWhile si legge come in inglese: 'prendi mentre meno di 100'." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/streams/stream-tolist.yaml b/translations/content/it/streams/stream-tolist.yaml new file mode 100644 index 0000000..d552618 --- /dev/null +++ b/translations/content/it/streams/stream-tolist.yaml @@ -0,0 +1,18 @@ +--- +title: Stream.toList() +oldApproach: Collectors.toList() +modernApproach: .toList() +summary: "Il terminale toList() sostituisce il verboso collect(Collectors.toList())." +explanation: "Stream.toList() restituisce una lista non modificabile. È equivalente a .collect(Collectors.toUnmodifiableList()) ma molto più breve. Nota: il risultato è immutabile, a differenza di Collectors.toList()." +whyModernWins: +- icon: 📏 + title: 7 caratteri vs 24 + desc: ".toList() sostituisce .collect(Collectors.toList())." +- icon: 🔒 + title: Immutabile + desc: "La lista risultante non può essere modificata." +- icon: 📖 + title: Fluente + desc: "Si legge naturalmente alla fine di una pipeline." +support: + description: Ampiamente disponibile dal JDK 16 (marzo 2021) diff --git a/translations/content/it/streams/virtual-thread-executor.yaml b/translations/content/it/streams/virtual-thread-executor.yaml new file mode 100644 index 0000000..89b0173 --- /dev/null +++ b/translations/content/it/streams/virtual-thread-executor.yaml @@ -0,0 +1,18 @@ +--- +title: Executor con thread virtuali +oldApproach: Pool di thread fisso +modernApproach: Executor con thread virtuali +summary: "Usa gli executor con thread virtuali per concorrenza leggera illimitata." +explanation: "L'executor con thread virtuali crea un nuovo thread virtuale per ogni task. Nessun dimensionamento del pool necessario — i thread virtuali sono abbastanza economici da crearne milioni." +whyModernWins: +- icon: ♾️ + title: Nessun dimensionamento + desc: "Nessuna dimensione del pool da ottimizzare — crea tutti i thread necessari." +- icon: ⚡ + title: Leggero + desc: "I thread virtuali usano KB di memoria, non MB." +- icon: 🧹 + title: Auto-chiudibile + desc: "Il try-with-resources gestisce automaticamente lo shutdown." +support: + description: Ampiamente disponibile dal JDK 21 LTS (settembre 2023) diff --git a/translations/content/it/strings/string-chars-stream.yaml b/translations/content/it/strings/string-chars-stream.yaml new file mode 100644 index 0000000..cfbda26 --- /dev/null +++ b/translations/content/it/strings/string-chars-stream.yaml @@ -0,0 +1,18 @@ +--- +title: Caratteri della stringa come stream +oldApproach: Loop manuale +modernApproach: Stream chars() +summary: "Elabora i caratteri della stringa come pipeline stream." +explanation: "String.chars() restituisce un IntStream di valori carattere, abilitando l'elaborazione funzionale. Per il supporto Unicode, codePoints() gestisce correttamente i caratteri supplementari." +whyModernWins: +- icon: 🔗 + title: Concatenabile + desc: "Usa filter, map, collect sugli stream di caratteri." +- icon: 📐 + title: Dichiarativo + desc: "Descrivi cosa fare, non come fare il loop." +- icon: 🌐 + title: Pronto per Unicode + desc: "codePoints() gestisce correttamente emoji e caratteri supplementari." +support: + description: "Disponibile dal JDK 8+ (migliorato in 9+)" diff --git a/translations/content/it/strings/string-formatted.yaml b/translations/content/it/strings/string-formatted.yaml new file mode 100644 index 0000000..592a52f --- /dev/null +++ b/translations/content/it/strings/string-formatted.yaml @@ -0,0 +1,18 @@ +--- +title: String.formatted() +oldApproach: String.format() +modernApproach: formatted() +summary: "Chiama formatted() sulla stringa template stessa." +explanation: "String.formatted() è un metodo di istanza equivalente a String.format() ma chiamato sulla stringa di formato. Si legge più naturalmente in un flusso da sinistra a destra." +whyModernWins: +- icon: 📖 + title: Si legge naturalmente + desc: "template.formatted(args) scorre meglio di String.format(template, args)." +- icon: 🔗 + title: Concatenabile + desc: "Può essere concatenato con altri metodi string." +- icon: 📏 + title: Meno verboso + desc: "Elimina la ridondante chiamata statica String.format()." +support: + description: Ampiamente disponibile dal JDK 15 (settembre 2020) diff --git a/translations/content/it/strings/string-indent-transform.yaml b/translations/content/it/strings/string-indent-transform.yaml new file mode 100644 index 0000000..f26a075 --- /dev/null +++ b/translations/content/it/strings/string-indent-transform.yaml @@ -0,0 +1,18 @@ +--- +title: String.indent() e transform() +oldApproach: Indentazione manuale +modernApproach: indent() / transform() +summary: "Indenta il testo e concatena le trasformazioni di stringa in modo fluente." +explanation: "indent(n) aggiunge n spazi a ogni riga. transform(fn) applica qualsiasi funzione e restituisce il risultato, abilitando la concatenazione fluente delle operazioni sulle stringhe." +whyModernWins: +- icon: 📏 + title: Integrato + desc: "L'indentazione è un'operazione comune — ora è una chiamata." +- icon: 🔗 + title: Concatenabile + desc: "transform() abilita pipeline fluenti sulle stringhe." +- icon: 🧹 + title: Codice pulito + desc: "Nessuna divisione manuale di righe e loop StringBuilder." +support: + description: Ampiamente disponibile dal JDK 12 (marzo 2019) diff --git a/translations/content/it/strings/string-isblank.yaml b/translations/content/it/strings/string-isblank.yaml new file mode 100644 index 0000000..a795078 --- /dev/null +++ b/translations/content/it/strings/string-isblank.yaml @@ -0,0 +1,18 @@ +--- +title: String.isBlank() +oldApproach: trim().isEmpty() +modernApproach: isBlank() +summary: "Controlla le stringhe vuote con una singola chiamata a metodo." +explanation: "isBlank() restituisce true se la stringa è vuota o contiene solo spazi bianchi, inclusi i caratteri di spazio bianco Unicode che trim() non riconosce." +whyModernWins: +- icon: �� + title: Auto-documentante + desc: "isBlank() dice esattamente cosa controlla." +- icon: 🌐 + title: Consapevole di Unicode + desc: "Gestisce tutti gli spazi bianchi Unicode, non solo ASCII." +- icon: ⚡ + title: Nessuna allocazione + desc: "Non viene creata alcuna stringa trimmed intermedia." +support: + description: Ampiamente disponibile dal JDK 11 (settembre 2018) diff --git a/translations/content/it/strings/string-lines.yaml b/translations/content/it/strings/string-lines.yaml new file mode 100644 index 0000000..305bf91 --- /dev/null +++ b/translations/content/it/strings/string-lines.yaml @@ -0,0 +1,18 @@ +--- +title: String.lines() per la divisione in righe +oldApproach: split("\\n") +modernApproach: lines() +summary: "Usa String.lines() per dividere il testo in uno stream di righe senza overhead regex." +explanation: "String.lines() restituisce uno Stream di righe divise per \n, \r o \r\n. È più lazy ed efficiente di split(), evita la compilazione regex e si integra naturalmente con l'API Stream per ulteriori elaborazioni." +whyModernWins: +- icon: ⚡ + title: Streaming lazy + desc: "Le righe vengono prodotte su richiesta, non tutte in una volta come split()." +- icon: 🔧 + title: Terminatori di riga universali + desc: "Gestisce automaticamente \n, \r e \r\n senza regex." +- icon: 🔗 + title: Integrazione Stream + desc: "Restituisce uno Stream per uso diretto con filter, map, collect." +support: + description: "Disponibile dal JDK 11 (settembre 2018)." diff --git a/translations/content/it/strings/string-repeat.yaml b/translations/content/it/strings/string-repeat.yaml new file mode 100644 index 0000000..c1cd453 --- /dev/null +++ b/translations/content/it/strings/string-repeat.yaml @@ -0,0 +1,18 @@ +--- +title: String.repeat() +oldApproach: Loop StringBuilder +modernApproach: repeat() +summary: "Ripeti una stringa n volte senza un loop." +explanation: "String.repeat(int) restituisce la stringa concatenata con se stessa n volte. Gestisce i casi limite: repeat(0) restituisce una stringa vuota, repeat(1) restituisce la stessa stringa." +whyModernWins: +- icon: 📏 + title: Una riga + desc: "Sostituisci 5 righe di codice StringBuilder con una chiamata." +- icon: ⚡ + title: Ottimizzato + desc: "L'implementazione interna è ottimizzata per le ripetizioni grandi." +- icon: 📖 + title: Intento chiaro + desc: "repeat(3) trasmette immediatamente lo scopo." +support: + description: Ampiamente disponibile dal JDK 11 (settembre 2018) diff --git a/translations/content/it/strings/string-strip.yaml b/translations/content/it/strings/string-strip.yaml new file mode 100644 index 0000000..9721647 --- /dev/null +++ b/translations/content/it/strings/string-strip.yaml @@ -0,0 +1,18 @@ +--- +title: String.strip() vs trim() +oldApproach: trim() +modernApproach: strip() +summary: "Usa stripping consapevole di Unicode con strip(), stripLeading(), stripTrailing()." +explanation: "trim() rimuove solo i caratteri ≤ U+0020 (caratteri di controllo ASCII e spazio). strip() usa Character.isWhitespace() che gestisce gli spazi Unicode come lo spazio unificatore, lo spazio ideografico, ecc." +whyModernWins: +- icon: 🌐 + title: Corretto per Unicode + desc: "Gestisce tutti i caratteri di spazio bianco da ogni script." +- icon: 🎯 + title: Direzionale + desc: "stripLeading() e stripTrailing() per il trimming su un solo lato." +- icon: 🛡️ + title: Meno bug + desc: "Nessun spazio bianco a sorpresa rimasto nel testo internazionale." +support: + description: Ampiamente disponibile dal JDK 11 (settembre 2018) diff --git a/translations/content/it/tooling/aot-class-preloading.yaml b/translations/content/it/tooling/aot-class-preloading.yaml new file mode 100644 index 0000000..555935e --- /dev/null +++ b/translations/content/it/tooling/aot-class-preloading.yaml @@ -0,0 +1,18 @@ +--- +title: Precaricamento AOT delle classi +oldApproach: Avvio a freddo ogni volta +modernApproach: Cache AOT +summary: "Metti in cache il caricamento delle classi e la compilazione per un avvio istantaneo." +explanation: "Il precaricamento AOT delle classi mette in cache le classi caricate e collegate da un'esecuzione di addestramento. Agli avvii successivi, le classi vengono caricate dalla cache, saltando la verifica e il collegamento. Combinato con la compilazione AOT, questo riduce drasticamente il tempo di avvio." +whyModernWins: +- icon: ⚡ + title: Avvio più veloce + desc: "Salta il caricamento, la verifica e il collegamento delle classi." +- icon: 📦 + title: Stato in cache + desc: "L'esecuzione di addestramento cattura lo stato ideale delle classi." +- icon: 🔧 + title: Nessuna modifica al codice + desc: "Funziona con le applicazioni esistenti — basta aggiungere flag JVM." +support: + description: "Disponibile come funzionalità standard nel JDK 25 LTS (JEP 514/515, settembre 2025)." diff --git a/translations/content/it/tooling/built-in-http-server.yaml b/translations/content/it/tooling/built-in-http-server.yaml new file mode 100644 index 0000000..00d10c1 --- /dev/null +++ b/translations/content/it/tooling/built-in-http-server.yaml @@ -0,0 +1,18 @@ +--- +title: Server HTTP integrato +oldApproach: Server esterno / Framework +modernApproach: CLI jwebserver +summary: "Java 18 include un server HTTP minimale integrato per la prototipazione e la servizione di file." +explanation: "JDK 18 ha aggiunto un semplice server HTTP di file senza dipendenze accessibile tramite lo strumento da riga di comando jwebserver o l'API SimpleFileServer. Serve file statici da una directory specifica senza configurazione. Lo strumento CLI è ideale per prototipazione rapida, test e condivisione di file ad hoc — nessuna dipendenza esterna o framework richiesto." +whyModernWins: +- icon: 🚀 + title: Zero setup + desc: "Esegui jwebserver in qualsiasi directory — nessuna installazione, configurazione o dipendenza necessaria." +- icon: 📦 + title: Integrato nel JDK + desc: "Disponibile in ogni installazione JDK 18+, sempre disponibile su qualsiasi macchina con Java." +- icon: 🧪 + title: Ottimo per la prototipazione + desc: "Servi file statici istantaneamente per testare HTML, API o sviluppo front-end." +support: + description: "Disponibile dal JDK 18 (marzo 2022)" diff --git a/translations/content/it/tooling/compact-object-headers.yaml b/translations/content/it/tooling/compact-object-headers.yaml new file mode 100644 index 0000000..8ca040c --- /dev/null +++ b/translations/content/it/tooling/compact-object-headers.yaml @@ -0,0 +1,18 @@ +--- +title: Header oggetto compatti +oldApproach: Header a 128 bit +modernApproach: Header a 64 bit +summary: "Riduci della metà la dimensione dell'header degli oggetti per una migliore densità di memoria e utilizzo della cache." +explanation: "Gli header oggetto compatti riducono l'overhead per oggetto da 128 bit a 64 bit sulle piattaforme a 64 bit. Questo risparmia memoria e migliora l'utilizzo della cache, specialmente per le applicazioni con molti oggetti piccoli." +whyModernWins: +- icon: 📦 + title: Header più piccoli del 50% + desc: "8 byte invece di 16 per oggetto." +- icon: ⚡ + title: Migliore utilizzo della cache + desc: "Più oggetti entrano nelle linee di cache della CPU." +- icon: 📊 + title: Maggiore densità + desc: "Più oggetti nello stesso heap." +support: + description: "Finalizzato nel JDK 25 LTS (JEP 519, settembre 2025)." diff --git a/translations/content/it/tooling/jfr-profiling.yaml b/translations/content/it/tooling/jfr-profiling.yaml new file mode 100644 index 0000000..94a42c3 --- /dev/null +++ b/translations/content/it/tooling/jfr-profiling.yaml @@ -0,0 +1,18 @@ +--- +title: JFR per il profiling +oldApproach: Profiler esterno +modernApproach: Java Flight Recorder +summary: "Profila qualsiasi app Java con il Flight Recorder integrato — nessuno strumento esterno." +explanation: "Java Flight Recorder (JFR) è uno strumento di profiling a basso overhead integrato nella JVM. Cattura eventi per CPU, memoria, GC, I/O, thread e eventi personalizzati con impatto minimo sulle prestazioni (~1%)." +whyModernWins: +- icon: 🆓 + title: Integrato + desc: "Nessun profiler esterno da installare o licenziare." +- icon: ⚡ + title: Basso overhead + desc: "~1% di impatto sulle prestazioni — sicuro per la produzione." +- icon: 📊 + title: Eventi ricchi + desc: "CPU, memoria, GC, thread, I/O, lock ed eventi personalizzati." +support: + description: "Ampiamente disponibile dal JDK 9/11 (open-source in 11)" diff --git a/translations/content/it/tooling/jshell-prototyping.yaml b/translations/content/it/tooling/jshell-prototyping.yaml new file mode 100644 index 0000000..f972877 --- /dev/null +++ b/translations/content/it/tooling/jshell-prototyping.yaml @@ -0,0 +1,18 @@ +--- +title: JShell per la prototipazione +oldApproach: Crea file + Compila + Esegui +modernApproach: REPL jshell +summary: "Prova le espressioni Java in modo interattivo senza creare file." +explanation: "JShell è un Read-Eval-Print Loop per Java. Testa espressioni, sperimenta con le API e prototipa codice senza creare file, compilare o scrivere un metodo main. Include completamento con tab e documentazione inline." +whyModernWins: +- icon: ⚡ + title: Feedback immediato + desc: "Digita un'espressione, vedi il risultato immediatamente." +- icon: 📝 + title: Nessun file necessario + desc: "Nessun file .java, nessun passo di compilazione." +- icon: 🔍 + title: Esplorazione delle API + desc: "Il completamento con tab aiuta a scoprire metodi e parametri." +support: + description: Ampiamente disponibile dal JDK 9 (settembre 2017) diff --git a/translations/content/it/tooling/junit6-with-jspecify.yaml b/translations/content/it/tooling/junit6-with-jspecify.yaml new file mode 100644 index 0000000..a85047f --- /dev/null +++ b/translations/content/it/tooling/junit6-with-jspecify.yaml @@ -0,0 +1,18 @@ +--- +title: JUnit 6 con sicurezza null JSpecify +oldApproach: API non annotata +modernApproach: API @NullMarked +summary: "JUnit 6 adotta JSpecify @NullMarked, rendendo espliciti i contratti null nell'intera API di asserzione." +explanation: "JUnit 5 è stato rilasciato senza annotazioni di nullabilità standardizzate, lasciando agli sviluppatori il compito di indovinare se i parametri di asserzione o i valori di ritorno potessero essere null. JUnit 6 adotta JSpecify nell'intero modulo: l'annotazione @NullMarked rende tutti i tipi non annotati non-null per default, e @Nullable contrassegna le eccezioni. La classe Assertions annota esplicitamente i parametri come assertNull(@Nullable Object actual) e fail(@Nullable String message), così IDE e analizzatori statici possono rilevare l'uso errato del null in fase di compilazione invece che a runtime." +whyModernWins: +- icon: 📜 + title: Contratti espliciti + desc: "@NullMarked sul modulo JUnit 6 documenta la semantica null direttamente nell'API — nessuna lettura del sorgente necessaria." +- icon: 🛡️ + title: Sicurezza in fase di compilazione + desc: "IDE e analizzatori avvisano quando viene passato null dove è atteso non-null, rilevando i bug prima dell'esecuzione dei test." +- icon: 🌐 + title: Standard dell'ecosistema + desc: "JSpecify è adottato da Spring, Guava e altri — semantica null coerente nell'intero stack." +support: + description: "Disponibile da JUnit 6.0 (ottobre 2025, richiede Java 17+)" diff --git a/translations/content/it/tooling/multi-file-source.yaml b/translations/content/it/tooling/multi-file-source.yaml new file mode 100644 index 0000000..632bfdd --- /dev/null +++ b/translations/content/it/tooling/multi-file-source.yaml @@ -0,0 +1,18 @@ +--- +title: Launcher multi-file sorgente +oldApproach: Compila tutto prima +modernApproach: Source Launcher +summary: "Avvia programmi multi-file senza un passo di compilazione esplicito." +explanation: "Java 22+ può compilare automaticamente i file sorgente referenziati quando si avvia da un file .java. Questo rende i piccoli programmi multi-file facili da eseguire come script, senza necessità di Maven o Gradle." +whyModernWins: +- icon: 🚀 + title: Zero setup + desc: "Nessuno strumento di build necessario per piccoli programmi multi-file." +- icon: 🔗 + title: Auto-risoluzione + desc: "Le classi referenziate vengono trovate e compilate automaticamente." +- icon: 📝 + title: Simile a script + desc: "Esegui programmi multi-file come script." +support: + description: "Disponibile dal JDK 22 (marzo 2024)" diff --git a/translations/content/it/tooling/single-file-execution.yaml b/translations/content/it/tooling/single-file-execution.yaml new file mode 100644 index 0000000..a784d4a --- /dev/null +++ b/translations/content/it/tooling/single-file-execution.yaml @@ -0,0 +1,18 @@ +--- +title: Esecuzione di file singoli +oldApproach: Compilazione in due passi +modernApproach: Avvio diretto +summary: "Esegui programmi Java a file singolo direttamente senza javac." +explanation: "Il launcher Java può compilare ed eseguire un singolo file sorgente in un comando. Combinato con il supporto shebang su Unix, i file Java possono funzionare come script. Nessun passo di compilazione separato necessario." +whyModernWins: +- icon: ⚡ + title: Un comando + desc: "java File.java compila ed esegue in un unico passo." +- icon: 📝 + title: Simile a script + desc: "Aggiungi una riga shebang per rendere i file .java script eseguibili." +- icon: 🎓 + title: Adatto all'apprendimento + desc: "I principianti eseguono il codice immediatamente senza imparare gli strumenti di build." +support: + description: Ampiamente disponibile dal JDK 11 (settembre 2018) diff --git a/translations/strings/it.yaml b/translations/strings/it.yaml new file mode 100644 index 0000000..0f9e414 --- /dev/null +++ b/translations/strings/it.yaml @@ -0,0 +1,90 @@ +site: + title: java.evolved + tagline: Java si è evoluto. Anche il tuo codice può. + tagline_line1: Java si è evoluto. + tagline_line2: Anche il tuo codice può. + description: Una raccolta di snippet Java moderni. Ogni vecchio pattern Java accanto + al suo sostituto moderno e pulito — fianco a fianco. + heroSnippetCount: ✦ {{snippetCount}} pattern moderni · Java 8 → Java 25 + heroOld: Vecchio + heroModern: Moderno + allComparisons: Tutti i confronti + snippetsBadge: '{{snippetCount}} snippet' +nav: + allPatterns: ← Tutti i pattern + toggleTheme: Cambia tema + viewOnGitHub: Vedi su GitHub + selectLanguage: Seleziona lingua +breadcrumb: + home: Home +sections: + codeComparison: Confronto Codice + whyModernWins: Perché vince l'approccio moderno + oldApproach: Approccio Vecchio + modernApproach: Approccio Moderno + sinceJdk: Dal JDK + difficulty: Difficoltà + jdkSupport: Supporto JDK + howItWorks: Come funziona + relatedDocs: Documentazione Correlata + relatedPatterns: Pattern correlati +filters: + show: 'Mostra:' + all: Tutti +difficulty: + beginner: Principiante + intermediate: Intermedio + advanced: Avanzato +search: + placeholder: Cerca snippet… + noResults: Nessun risultato trovato. + esc: ESC + searchTrigger: Cerca… + navigate: naviga + open: apri + close: chiudi +cards: + old: Vecchio + modern: Moderno + hoverHint: passa il mouse per vedere il moderno → + hoverHintRelated: Passa il mouse per vedere il moderno ➜ + touchHint: 👆 tocca o scorri → +copy: + copy: Copia + copied: Copiato! +share: + label: Condividi +view: + expandAll: Espandi Tutto + collapseAll: Comprimi Tutto +stats: + modernPatterns: Pattern Moderni + jdkVersions: Versioni JDK Coperte + categories: Categorie + linesOfPython: Righe di Python Richieste +footer: + tagline: Java si è evoluto. Anche il tuo codice può. + madeWith: Fatto con ❤️ da + and: e + inspiredBy: Ispirato da + viewOnGitHub: Vedi su GitHub +copilot: + headline: Modernizza il tuo codice Java con GitHub Copilot. + description: Lascia che Copilot ti aiuti a migrare i pattern legacy a Java moderno + — automaticamente. + appModernization: Modernizzazione App → + javaGuide: Guida Java → +support: + available: Disponibile + preview: Anteprima + experimental: Sperimentale +contribute: + button: Contribuisci + codeIssue: Segnala un problema nel codice + translationIssue: Segnala un problema di traduzione + suggestPattern: Suggerisci un nuovo pattern + seeIssue: "Vedi un problema con questo codice?" + reportIt: "Faccelo sapere." +untranslated: + notice: Questa pagina non è ancora stata tradotta in {{localeName}}. + viewInEnglish: Visualizza in Inglese From b303be9e5282f085e2afc4a4f9ed21e5a777916f Mon Sep 17 00:00:00 2001 From: Bruno Borges Date: Thu, 26 Feb 2026 17:07:16 -0500 Subject: [PATCH 05/28] =?UTF-8?q?Add=20"learn=20more=20=E2=86=92"=20text?= =?UTF-8?q?=20to=20index=20card=20arrow=20links?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the bare → arrow in card footers with a translated "learn more →" label for all 9 locales, making the clickable action explicit. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- html-generators/generate.java | 3 ++- templates/index-card.html | 2 +- translations/strings/ar.yaml | 1 + translations/strings/de.yaml | 1 + translations/strings/en.yaml | 1 + translations/strings/es.yaml | 1 + translations/strings/fr.yaml | 1 + translations/strings/ja.yaml | 1 + translations/strings/ko.yaml | 1 + translations/strings/pt-BR.yaml | 1 + translations/strings/zh-CN.yaml | 1 + 11 files changed, 12 insertions(+), 2 deletions(-) diff --git a/html-generators/generate.java b/html-generators/generate.java index 12a2f92..edab941 100644 --- a/html-generators/generate.java +++ b/html-generators/generate.java @@ -366,7 +366,8 @@ String renderIndexCard(String tpl, Snippet s, String locale, Map Map.entry("jdkVersion", s.jdkVersion()), Map.entry("cardHref", cardHref), Map.entry("cards.old", strings.getOrDefault("cards.old", "Old")), Map.entry("cards.modern", strings.getOrDefault("cards.modern", "Modern")), - Map.entry("cards.hoverHint", strings.getOrDefault("cards.hoverHint", "hover to see modern →")))); + Map.entry("cards.hoverHint", strings.getOrDefault("cards.hoverHint", "hover to see modern →")), + Map.entry("cards.learnMore", strings.getOrDefault("cards.learnMore", "learn more")))); } String renderWhyCards(String tpl, JsonNode whyList) { diff --git a/templates/index-card.html b/templates/index-card.html index 0117fdf..86f9067 100644 --- a/templates/index-card.html +++ b/templates/index-card.html @@ -18,6 +18,6 @@

{{title}}

\ No newline at end of file diff --git a/translations/strings/ar.yaml b/translations/strings/ar.yaml index 98af26c..c2054d7 100644 --- a/translations/strings/ar.yaml +++ b/translations/strings/ar.yaml @@ -47,6 +47,7 @@ cards: hoverHint: "مرر للرؤية الحديث ←" hoverHintRelated: "مرر للرؤية الحديث ←" touchHint: "👆 انقر أو اسحب ←" + learnMore: اعرف المزيد copy: copy: نسخ copied: "تم النسخ!" diff --git a/translations/strings/de.yaml b/translations/strings/de.yaml index 633e70f..2fc3d19 100644 --- a/translations/strings/de.yaml +++ b/translations/strings/de.yaml @@ -49,6 +49,7 @@ cards: hoverHint: Hover für Modernes → hoverHintRelated: Hover für Modernes ➜ touchHint: 👆 tippen oder wischen → + learnMore: mehr erfahren copy: copy: Kopieren copied: Kopiert! diff --git a/translations/strings/en.yaml b/translations/strings/en.yaml index 4a739a2..8be28f2 100644 --- a/translations/strings/en.yaml +++ b/translations/strings/en.yaml @@ -49,6 +49,7 @@ cards: hoverHint: hover to see modern → hoverHintRelated: Hover to see modern ➜ touchHint: 👆 tap or swipe → + learnMore: learn more copy: copy: Copy copied: Copied! diff --git a/translations/strings/es.yaml b/translations/strings/es.yaml index ccae83e..f6bf10a 100644 --- a/translations/strings/es.yaml +++ b/translations/strings/es.yaml @@ -49,6 +49,7 @@ cards: hoverHint: pasa el ratón para ver el moderno → hoverHintRelated: Pasa el ratón para ver el moderno ➜ touchHint: 👆 toca o desliza → + learnMore: saber más copy: copy: Copiar copied: ¡Copiado! diff --git a/translations/strings/fr.yaml b/translations/strings/fr.yaml index cf5e8fc..3e48a9f 100644 --- a/translations/strings/fr.yaml +++ b/translations/strings/fr.yaml @@ -49,6 +49,7 @@ cards: hoverHint: survolez pour voir le moderne → hoverHintRelated: Survolez pour voir le moderne ➜ touchHint: 👆 appuyez ou glissez → + learnMore: en savoir plus copy: copy: Copier copied: Copié ! diff --git a/translations/strings/ja.yaml b/translations/strings/ja.yaml index ad74854..148c402 100644 --- a/translations/strings/ja.yaml +++ b/translations/strings/ja.yaml @@ -47,6 +47,7 @@ cards: hoverHint: ホバーしてモダンを見る → hoverHintRelated: ホバーしてモダンを見る ➜ touchHint: 👆 タップまたはスワイプ → + learnMore: 詳しく見る copy: copy: コピー copied: コピーしました! diff --git a/translations/strings/ko.yaml b/translations/strings/ko.yaml index 7c3007a..bff3266 100644 --- a/translations/strings/ko.yaml +++ b/translations/strings/ko.yaml @@ -47,6 +47,7 @@ cards: hoverHint: 마우스를 올려 모던 코드 보기 → hoverHintRelated: 마우스를 올려 모던 코드 보기 ➜ touchHint: 👆 탭하거나 스와이프 → + learnMore: 자세히 보기 copy: copy: 복사 copied: 복사됨! diff --git a/translations/strings/pt-BR.yaml b/translations/strings/pt-BR.yaml index 8d95363..04076c7 100644 --- a/translations/strings/pt-BR.yaml +++ b/translations/strings/pt-BR.yaml @@ -48,6 +48,7 @@ cards: hoverHint: passe o mouse para ver o moderno → hoverHintRelated: Passe o mouse para ver o moderno ➜ touchHint: 👆 toque ou deslize → + learnMore: saiba mais copy: copy: Copiar copied: Copiado! diff --git a/translations/strings/zh-CN.yaml b/translations/strings/zh-CN.yaml index 4d24f1c..dae68e9 100644 --- a/translations/strings/zh-CN.yaml +++ b/translations/strings/zh-CN.yaml @@ -48,6 +48,7 @@ cards: hoverHint: 悬停查看现代版 → hoverHintRelated: 悬停查看现代版 ➜ touchHint: 👆 点击或滑动 → + learnMore: 了解更多 copy: copy: 复制 copied: 已复制! From ea485eb2d66a790d2a8c61004fe044fa137a3980 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Feb 2026 23:47:19 +0000 Subject: [PATCH 06/28] Fix corrupted emoji icons in Italian translation files Co-authored-by: brunoborges <129743+brunoborges@users.noreply.github.com> --- translations/content/it/io/io-class-console-io.yaml | 2 +- translations/content/it/strings/string-isblank.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/translations/content/it/io/io-class-console-io.yaml b/translations/content/it/io/io-class-console-io.yaml index d5d9970..e6b7049 100644 --- a/translations/content/it/io/io-class-console-io.yaml +++ b/translations/content/it/io/io-class-console-io.yaml @@ -11,7 +11,7 @@ whyModernWins: - icon: 🔒 title: Nessuna perdita di risorse desc: "Nessun Scanner da chiudere — i metodi IO gestiscono internamente le risorse." -- icon: �� +- icon: 🎓 title: Adatto ai principianti desc: "I nuovi sviluppatori possono fare I/O da console senza imparare Scanner, System.out o le istruzioni import." support: diff --git a/translations/content/it/strings/string-isblank.yaml b/translations/content/it/strings/string-isblank.yaml index a795078..9feca2c 100644 --- a/translations/content/it/strings/string-isblank.yaml +++ b/translations/content/it/strings/string-isblank.yaml @@ -5,7 +5,7 @@ modernApproach: isBlank() summary: "Controlla le stringhe vuote con una singola chiamata a metodo." explanation: "isBlank() restituisce true se la stringa è vuota o contiene solo spazi bianchi, inclusi i caratteri di spazio bianco Unicode che trim() non riconosce." whyModernWins: -- icon: �� +- icon: 📖 title: Auto-documentante desc: "isBlank() dice esattamente cosa controlla." - icon: 🌐 From 6d7ccf7460512e86199270b02d62feedeadc39ac Mon Sep 17 00:00:00 2001 From: Artur Skowronski Date: Fri, 27 Feb 2026 13:20:38 +0100 Subject: [PATCH 07/28] feat(i18n): add initial Polish locale translations --- README.md | 2 +- html-generators/locales.properties | 1 + .../pl/collections/collectors-teeing.yaml | 17 ++++ .../completablefuture-chaining.yaml | 17 ++++ .../content/pl/datetime/date-formatting.yaml | 17 ++++ .../ejb-timer-vs-jakarta-scheduler.yaml | 17 ++++ .../content/pl/errors/helpful-npe.yaml | 17 ++++ .../pl/io/deserialization-filters.yaml | 17 ++++ .../compact-canonical-constructor.yaml | 17 ++++ .../pl/language/type-inference-with-var.yaml | 17 ++++ .../pl/security/key-derivation-functions.yaml | 17 ++++ .../pl/streams/collectors-flatmapping.yaml | 17 ++++ .../pl/strings/string-chars-stream.yaml | 17 ++++ .../pl/tooling/aot-class-preloading.yaml | 17 ++++ translations/strings/pl.yaml | 88 +++++++++++++++++++ 15 files changed, 294 insertions(+), 1 deletion(-) create mode 100644 translations/content/pl/collections/collectors-teeing.yaml create mode 100644 translations/content/pl/concurrency/completablefuture-chaining.yaml create mode 100644 translations/content/pl/datetime/date-formatting.yaml create mode 100644 translations/content/pl/enterprise/ejb-timer-vs-jakarta-scheduler.yaml create mode 100644 translations/content/pl/errors/helpful-npe.yaml create mode 100644 translations/content/pl/io/deserialization-filters.yaml create mode 100644 translations/content/pl/language/compact-canonical-constructor.yaml create mode 100644 translations/content/pl/language/type-inference-with-var.yaml create mode 100644 translations/content/pl/security/key-derivation-functions.yaml create mode 100644 translations/content/pl/streams/collectors-flatmapping.yaml create mode 100644 translations/content/pl/strings/string-chars-stream.yaml create mode 100644 translations/content/pl/tooling/aot-class-preloading.yaml create mode 100644 translations/strings/pl.yaml diff --git a/README.md b/README.md index ad1a6d7..622c55d 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Generated files (`site/category/*.html`, `site/{locale}/`, and `site/data/snippe ### Internationalization -The site supports 9 languages: English, Deutsch, Español, Português (Brasil), 中文 (简体), العربية, Français, 日本語, and 한국어. See [`specs/i18n/i18n-spec.md`](specs/i18n/i18n-spec.md) for the full specification. +The site supports 10 languages: English, Deutsch, Español, Português (Brasil), 中文 (简体), العربية, Français, 日本語, 한국어, and Polski. See [`specs/i18n/i18n-spec.md`](specs/i18n/i18n-spec.md) for the full specification. ## Build & run locally diff --git a/html-generators/locales.properties b/html-generators/locales.properties index 1013c65..ff07165 100644 --- a/html-generators/locales.properties +++ b/html-generators/locales.properties @@ -8,3 +8,4 @@ ar=🇸🇦 العربية fr=🇫🇷 Français ja=🇯🇵 日本語 ko=🇰🇷 한국어 +pl=🇵🇱 Polski diff --git a/translations/content/pl/collections/collectors-teeing.yaml b/translations/content/pl/collections/collectors-teeing.yaml new file mode 100644 index 0000000..2460050 --- /dev/null +++ b/translations/content/pl/collections/collectors-teeing.yaml @@ -0,0 +1,17 @@ +title: Collectors.teeing() +oldApproach: Dwa przebiegi +modernApproach: teeing() +summary: Oblicz dwa agregaty w jednym przebiegu strumienia. +explanation: Collectors.teeing() przekazuje każdy element do dwóch kolektorów downstream i scala wyniki. Dzięki temu nie trzeba przetwarzać danych dwa razy ani używać mutowalnego akumulatora. +whyModernWins: + - icon: ⚡ + title: Jeden przebieg + desc: Przetwarzasz strumień raz zamiast dwa razy. + - icon: 🧩 + title: Kompozycyjność + desc: Możesz połączyć dowolne dwa kolektory funkcją scalającą. + - icon: 🔒 + title: Niemutowalny wynik + desc: Wynik można od razu scalić do rekordu lub obiektu wartości. +support: + description: Szeroko dostępne od JDK 12 (marzec 2019) diff --git a/translations/content/pl/concurrency/completablefuture-chaining.yaml b/translations/content/pl/concurrency/completablefuture-chaining.yaml new file mode 100644 index 0000000..7dc5391 --- /dev/null +++ b/translations/content/pl/concurrency/completablefuture-chaining.yaml @@ -0,0 +1,17 @@ +title: Łańcuchowanie CompletableFuture +oldApproach: Blokujące Future.get() +modernApproach: CompletableFuture +summary: Łącz operacje asynchroniczne bez blokowania, używając CompletableFuture. +explanation: CompletableFuture pozwala budować nieblokujące potoki async. Łącz kroki przez thenApply, thenCompose i thenAccept. Błędy obsługuj przez exceptionally(). Wiele future można łączyć przez allOf/anyOf. +whyModernWins: + - icon: 🔗 + title: Łańcuchowanie + desc: Składasz kroki asynchroniczne w czytelny pipeline. + - icon: 🚫 + title: Bez blokowania + desc: Żaden wątek nie czeka bezczynnie na wynik. + - icon: 🛡️ + title: Obsługa błędów + desc: exceptionally() i handle() upraszczają odzyskiwanie po błędach. +support: + description: Szeroko dostępne od JDK 8 (marzec 2014) diff --git a/translations/content/pl/datetime/date-formatting.yaml b/translations/content/pl/datetime/date-formatting.yaml new file mode 100644 index 0000000..6fc3f96 --- /dev/null +++ b/translations/content/pl/datetime/date-formatting.yaml @@ -0,0 +1,17 @@ +title: Formatowanie dat +oldApproach: SimpleDateFormat +modernApproach: DateTimeFormatter +summary: Formatuj daty przez niezmienny i bezpieczny wątkowo DateTimeFormatter. +explanation: DateTimeFormatter jest niemutowalny i bezpieczny wątkowo, w przeciwieństwie do SimpleDateFormat. Możesz przechowywać go jako stałą i współdzielić. Dla typowych formatów dostępne są gotowe formattery, np. ISO_LOCAL_DATE. +whyModernWins: + - icon: 🛡️ + title: Bezpieczeństwo wątkowe + desc: Możesz współdzielić formattery między wątkami bez synchronizacji. + - icon: 📋 + title: Wbudowane formaty + desc: ISO_LOCAL_DATE, ISO_INSTANT i inne standardowe formaty. + - icon: 🔒 + title: Niemutowalność + desc: Formatter można bezpiecznie trzymać jako static final. +support: + description: Szeroko dostępne od JDK 8 (marzec 2014) diff --git a/translations/content/pl/enterprise/ejb-timer-vs-jakarta-scheduler.yaml b/translations/content/pl/enterprise/ejb-timer-vs-jakarta-scheduler.yaml new file mode 100644 index 0000000..8accc7b --- /dev/null +++ b/translations/content/pl/enterprise/ejb-timer-vs-jakarta-scheduler.yaml @@ -0,0 +1,17 @@ +title: EJB Timer vs Jakarta Scheduler +oldApproach: EJB TimerService +modernApproach: ManagedScheduledExecutorService +summary: Zastąp ciężkie timery EJB prostszym harmonogramowaniem przez ManagedScheduledExecutorService z Jakarta Concurrency. +explanation: Timery EJB wymagają beana @Stateless lub @Singleton, callbacku @Timeout i wyrażeń harmonogramu w adnotacjach albo XML. Jakarta Concurrency udostępnia ManagedScheduledExecutorService z dobrze znanym API java.util.concurrent. To mniej boilerplate, łatwiejsze testy jednostkowe i brak zależności od kontenera EJB. +whyModernWins: + - icon: 🪶 + title: Mniej boilerplate + desc: Bez callbacku @Timeout i ScheduleExpression, używasz standardowego API ScheduledExecutorService. + - icon: 🧪 + title: Lepsza testowalność + desc: Zwykłe metody i mocki executora upraszczają testy bez kontenera EJB. + - icon: ☁️ + title: Podejście cloud-native + desc: Managed executory integrują się z cyklem życia kontenera i działają w lekkich runtime'ach. +support: + description: Dostępne od Jakarta EE 10 / Concurrency 3.0 diff --git a/translations/content/pl/errors/helpful-npe.yaml b/translations/content/pl/errors/helpful-npe.yaml new file mode 100644 index 0000000..238af77 --- /dev/null +++ b/translations/content/pl/errors/helpful-npe.yaml @@ -0,0 +1,17 @@ +title: Pomocne NullPointerException +oldApproach: Nieczytelny NPE +modernApproach: Szczegółowy NPE +summary: JVM automatycznie wskazuje dokładnie, która zmienna miała wartość null. +explanation: Helpful NPE opisuje, które wyrażenie było null i jaka operacja się nie powiodła. Od Java 14 jest to domyślnie włączone, bez zmian w kodzie, wystarczy nowsze JDK. +whyModernWins: + - icon: 🔍 + title: Dokładna zmienna + desc: Komunikat wskazuje konkretną zmienną null w łańcuchu wywołań. + - icon: ⚡ + title: Szybsze debugowanie + desc: Koniec zgadywania, które z wielu wywołań zwróciło null. + - icon: 🆓 + title: Darmowe usprawnienie + desc: Bez zmian w kodzie, po prostu uruchamiasz na JDK 14+. +support: + description: Szeroko dostępne od JDK 14 (marzec 2020) diff --git a/translations/content/pl/io/deserialization-filters.yaml b/translations/content/pl/io/deserialization-filters.yaml new file mode 100644 index 0000000..b3ddbd3 --- /dev/null +++ b/translations/content/pl/io/deserialization-filters.yaml @@ -0,0 +1,17 @@ +title: Filtry deserializacji +oldApproach: Akceptuj wszystko +modernApproach: ObjectInputFilter +summary: Ograniczaj klasy, które można deserializować, aby zapobiegać atakom. +explanation: ObjectInputFilter pozwala tworzyć allowlisty i denylisty klas, ograniczać głębokość grafu obiektów, rozmiary tablic i liczbę referencji. Chroni to przed podatnościami deserializacji bez dodatkowych bibliotek. +whyModernWins: + - icon: 🛡️ + title: Bezpieczeństwo + desc: Blokuje deserializację nieoczekiwanych lub złośliwych klas. + - icon: 📐 + title: Precyzyjna kontrola + desc: Kontrolujesz głębokość, rozmiary tablic, referencje i wzorce klas. + - icon: 🏗️ + title: Ochrona całego JVM + desc: Możesz ustawić globalny filtr dla całej deserializacji w JVM. +support: + description: Szeroko dostępne od JDK 9 (wrzesień 2017) diff --git a/translations/content/pl/language/compact-canonical-constructor.yaml b/translations/content/pl/language/compact-canonical-constructor.yaml new file mode 100644 index 0000000..38e50fe --- /dev/null +++ b/translations/content/pl/language/compact-canonical-constructor.yaml @@ -0,0 +1,17 @@ +title: Zwarty konstruktor kanoniczny +oldApproach: Jawna walidacja w konstruktorze +modernApproach: Konstruktor zwarty +summary: Waliduj i normalizuj pola rekordów bez powtarzania listy parametrów. +explanation: Rekordy mogą definiować zwarty konstruktor kanoniczny bez listy parametrów i bez ręcznych przypisań pól. Kompilator automatycznie przypisze parametry do pól po wykonaniu logiki walidacji. To idealne miejsce na preconditions, defensywne kopie i normalizację. +whyModernWins: + - icon: ✂️ + title: Mniej powtórzeń + desc: Nie musisz powtarzać parametrów ani ręcznie przypisywać każdego pola. + - icon: 🛡️ + title: Walidacja + desc: Świetne miejsce na null checki, walidację zakresu i defensywne kopie. + - icon: 📖 + title: Czytelniejsza intencja + desc: Zwarta składnia podkreśla walidację zamiast boilerplate. +support: + description: Szeroko dostępne od JDK 16 (marzec 2021) diff --git a/translations/content/pl/language/type-inference-with-var.yaml b/translations/content/pl/language/type-inference-with-var.yaml new file mode 100644 index 0000000..122d61c --- /dev/null +++ b/translations/content/pl/language/type-inference-with-var.yaml @@ -0,0 +1,17 @@ +title: Inferencja typów z var +oldApproach: Jawne typy +modernApproach: Słowo kluczowe var +summary: Używaj var do inferencji typów zmiennych lokalnych, mniej szumu i taka sama kontrola typów. +explanation: Od Java 10 kompilator wywnioskuje typ zmiennej lokalnej na podstawie prawej strony przypisania. To ogranicza wizualny szum bez utraty bezpieczeństwa typów. Używaj var, gdy typ jest oczywisty z kontekstu. +whyModernWins: + - icon: ⚡ + title: Mniej boilerplate + desc: Nie trzeba powtarzać złożonych typów generycznych po obu stronach przypisania. + - icon: 👁 + title: Lepsza czytelność + desc: Skupiasz się na nazwach zmiennych i wartościach, a nie na deklaracjach typów. + - icon: 🔒 + title: Nadal bezpieczne typowanie + desc: Kompilator wywnioskuje i egzekwuje dokładny typ już podczas kompilacji. +support: + description: Szeroko dostępne od JDK 10 (marzec 2018) diff --git a/translations/content/pl/security/key-derivation-functions.yaml b/translations/content/pl/security/key-derivation-functions.yaml new file mode 100644 index 0000000..efba613 --- /dev/null +++ b/translations/content/pl/security/key-derivation-functions.yaml @@ -0,0 +1,17 @@ +title: Funkcje wyprowadzania kluczy +oldApproach: Ręczne PBKDF2 +modernApproach: API KDF +summary: Wyprowadzaj klucze kryptograficzne przez standardowe API KDF. +explanation: API KDF udostępnia standardowy interfejs do funkcji wyprowadzania kluczy, w tym HKDF. Zastępuje nieporęczny wzorzec SecretKeyFactory + PBEKeySpec czytelnym API opartym o builder. +whyModernWins: + - icon: 📐 + title: Czyste API + desc: Wzorzec builder zamiast nieporęcznych konstruktorów KeySpec. + - icon: 🔧 + title: Obsługa HKDF + desc: Nowoczesny HKDF obok PBKDF2. + - icon: 🛡️ + title: Standard + desc: Jednolite API dla różnych algorytmów wyprowadzania kluczy. +support: + description: Ustabilizowane w JDK 25 LTS (JEP 510, wrzesień 2025) diff --git a/translations/content/pl/streams/collectors-flatmapping.yaml b/translations/content/pl/streams/collectors-flatmapping.yaml new file mode 100644 index 0000000..6c8644c --- /dev/null +++ b/translations/content/pl/streams/collectors-flatmapping.yaml @@ -0,0 +1,17 @@ +title: Collectors.flatMapping() +oldApproach: Zagnieżdżone flatMap +modernApproach: flatMapping() +summary: Użyj flatMapping() do spłaszczania wewnątrz kolektora grupującego. +explanation: Collectors.flatMapping() stosuje mapowanie one-to-many jako kolektor downstream. To odpowiednik Stream.flatMap() po stronie kolektorów, przydatny np. wewnątrz groupingBy lub partitioningBy. +whyModernWins: + - icon: 🧩 + title: Kompozycyjność + desc: Działa jako kolektor downstream wewnątrz groupingBy. + - icon: 📐 + title: Jeden przebieg + desc: Spłaszczanie i grupowanie wykonujesz w jednym przejściu strumienia. + - icon: 🔗 + title: Zagnieżdżanie + desc: Łatwo łączysz z innymi kolektorami downstream. +support: + description: Szeroko dostępne od JDK 9 (wrzesień 2017) diff --git a/translations/content/pl/strings/string-chars-stream.yaml b/translations/content/pl/strings/string-chars-stream.yaml new file mode 100644 index 0000000..b2f6c1b --- /dev/null +++ b/translations/content/pl/strings/string-chars-stream.yaml @@ -0,0 +1,17 @@ +title: Znaki String jako strumień +oldApproach: Ręczna pętla +modernApproach: chars() Stream +summary: Przetwarzaj znaki Stringa jako pipeline strumieniowy. +explanation: String.chars() zwraca IntStream wartości znaków i umożliwia funkcyjne przetwarzanie. Dla pełnego wsparcia Unicode użyj codePoints(), które poprawnie obsługuje znaki uzupełniające. +whyModernWins: + - icon: 🔗 + title: Łańcuchowanie + desc: Możesz używać filter, map i collect na strumieniach znaków. + - icon: 📐 + title: Deklaratywność + desc: Opisujesz co chcesz zrobić, a nie jak iterować. + - icon: 🌐 + title: Gotowość na Unicode + desc: codePoints() poprawnie obsługuje emoji i znaki uzupełniające. +support: + description: Dostępne od JDK 8+ (ulepszone w 9+) diff --git a/translations/content/pl/tooling/aot-class-preloading.yaml b/translations/content/pl/tooling/aot-class-preloading.yaml new file mode 100644 index 0000000..a676130 --- /dev/null +++ b/translations/content/pl/tooling/aot-class-preloading.yaml @@ -0,0 +1,17 @@ +title: AOT preloading klas +oldApproach: Zimny start za każdym razem +modernApproach: AOT Cache +summary: Buforuj ładowanie klas i kompilację, aby uzyskać szybszy start aplikacji. +explanation: AOT class preloading buforuje załadowane i zlinkowane klasy z przebiegu treningowego. Przy kolejnych uruchomieniach klasy są ładowane z cache, z pominięciem weryfikacji i linkowania. W połączeniu z kompilacją AOT znacząco skraca to czas startu. +whyModernWins: + - icon: ⚡ + title: Szybszy start + desc: Pomijasz ładowanie klas, weryfikację i linkowanie. + - icon: 📦 + title: Stan w cache + desc: Przebieg treningowy zapisuje optymalny stan klas. + - icon: 🔧 + title: Bez zmian w kodzie + desc: Działa z istniejącymi aplikacjami, wystarczy dodać flagi JVM. +support: + description: Dostępne jako standardowa funkcja w JDK 25 LTS (JEP 514/515, wrzesień 2025) diff --git a/translations/strings/pl.yaml b/translations/strings/pl.yaml new file mode 100644 index 0000000..ba66c2b --- /dev/null +++ b/translations/strings/pl.yaml @@ -0,0 +1,88 @@ +site: + title: java.evolved + tagline: Java ewoluowała. Twój kod też może. + tagline_line1: Java ewoluowała. + tagline_line2: Twój kod też może. + description: Zbiór nowoczesnych snippetów Java. Każdy stary wzorzec Java obok jego czystego, nowoczesnego odpowiednika. + heroSnippetCount: ✦ {{snippetCount}} nowoczesnych wzorców · Java 8 → Java 25 + heroOld: Stare + heroModern: Nowe + allComparisons: Wszystkie porównania + snippetsBadge: '{{snippetCount}} snippetów' +nav: + allPatterns: ← Wszystkie wzorce + toggleTheme: Przełącz motyw + viewOnGitHub: Zobacz na GitHub + selectLanguage: Wybierz język +breadcrumb: + home: Strona główna +sections: + codeComparison: Porównanie kodu + whyModernWins: Dlaczego nowoczesne podejście wygrywa + oldApproach: Stare podejście + modernApproach: Nowoczesne podejście + sinceJdk: Od JDK + difficulty: Poziom trudności + jdkSupport: Wsparcie JDK + howItWorks: Jak to działa + relatedDocs: Powiązana dokumentacja + relatedPatterns: Powiązane wzorce +filters: + show: 'Pokaż:' + all: Wszystkie +difficulty: + beginner: Początkujący + intermediate: Średniozaawansowany + advanced: Zaawansowany +search: + placeholder: Szukaj snippetów… + noResults: Brak wyników. + esc: ESC + searchTrigger: Szukaj… + navigate: nawiguj + open: otwórz + close: zamknij +cards: + old: Stare + modern: Nowe + hoverHint: najedź, aby zobaczyć nową wersję → + hoverHintRelated: Najedź, aby zobaczyć nową wersję ➜ + touchHint: 👆 dotknij lub przesuń → +copy: + copy: Kopiuj + copied: Skopiowano! +share: + label: Udostępnij +view: + expandAll: Rozwiń wszystko + collapseAll: Zwiń wszystko +stats: + modernPatterns: Nowoczesne wzorce + jdkVersions: Obsługiwane wersje JDK + categories: Kategorie + linesOfPython: Linie Pythona wymagane +footer: + tagline: Java ewoluowała. Twój kod też może. + madeWith: Stworzone z ❤️ przez + and: i + inspiredBy: Inspiracja + viewOnGitHub: Zobacz na GitHub +copilot: + headline: Modernizuj swój kod Java z GitHub Copilot. + description: Pozwól Copilotowi automatycznie migrować stare wzorce do nowoczesnej Javy. + appModernization: Modernizacja aplikacji → + javaGuide: Przewodnik po Javie → +support: + available: Dostępne + preview: Preview + experimental: Eksperymentalne +contribute: + button: Współtwórz + codeIssue: Zgłoś problem w kodzie + translationIssue: Zgłoś problem z tłumaczeniem + suggestPattern: Zaproponuj nowy wzorzec + seeIssue: "Widzisz problem z tym kodem?" + reportIt: "Daj nam znać." +untranslated: + notice: Ta strona nie została jeszcze przetłumaczona na {{localeName}}. + viewInEnglish: Zobacz po angielsku From 6108c8479088d56fbba3b059a6e395197b39f20a Mon Sep 17 00:00:00 2001 From: Artur Skowronski Date: Fri, 27 Feb 2026 13:29:30 +0100 Subject: [PATCH 08/28] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 622c55d..bca85d4 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Generated files (`site/category/*.html`, `site/{locale}/`, and `site/data/snippe ### Internationalization -The site supports 10 languages: English, Deutsch, Español, Português (Brasil), 中文 (简体), العربية, Français, 日本語, 한국어, and Polski. See [`specs/i18n/i18n-spec.md`](specs/i18n/i18n-spec.md) for the full specification. +The site supports 11 languages: English, Deutsch, Español, Português (Brasil), 中文 (简体), العربية, Français, 日本語, 한국어, Italian and Polski. See [`specs/i18n/i18n-spec.md`](specs/i18n/i18n-spec.md) for the full specification. ## Build & run locally From 2e003d83d734376833af79d83afe5e032e4f95cf Mon Sep 17 00:00:00 2001 From: Artur Skowronski Date: Fri, 27 Feb 2026 13:32:21 +0100 Subject: [PATCH 09/28] Update completablefuture-chaining.yaml --- .../content/pl/concurrency/completablefuture-chaining.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/translations/content/pl/concurrency/completablefuture-chaining.yaml b/translations/content/pl/concurrency/completablefuture-chaining.yaml index 7dc5391..4019ac2 100644 --- a/translations/content/pl/concurrency/completablefuture-chaining.yaml +++ b/translations/content/pl/concurrency/completablefuture-chaining.yaml @@ -1,11 +1,11 @@ -title: Łańcuchowanie CompletableFuture +title: Łączenie CompletableFuture oldApproach: Blokujące Future.get() modernApproach: CompletableFuture summary: Łącz operacje asynchroniczne bez blokowania, używając CompletableFuture. -explanation: CompletableFuture pozwala budować nieblokujące potoki async. Łącz kroki przez thenApply, thenCompose i thenAccept. Błędy obsługuj przez exceptionally(). Wiele future można łączyć przez allOf/anyOf. +explanation: CompletableFuture pozwala budować nieblokujące asynchroniczne potoki. Łącz kroki przez thenApply, thenCompose i thenAccept. Błędy obsługuj przez exceptionally(). Wiele future można łączyć przez allOf/anyOf. whyModernWins: - icon: 🔗 - title: Łańcuchowanie + title: Umożliwia łączenie operacji desc: Składasz kroki asynchroniczne w czytelny pipeline. - icon: 🚫 title: Bez blokowania From 75ed66cd7f20f0fe2208fad43e15e146e4f500e5 Mon Sep 17 00:00:00 2001 From: Artur Skowronski Date: Fri, 27 Feb 2026 13:32:46 +0100 Subject: [PATCH 10/28] Update date-formatting.yaml --- translations/content/pl/datetime/date-formatting.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/translations/content/pl/datetime/date-formatting.yaml b/translations/content/pl/datetime/date-formatting.yaml index 6fc3f96..a9bba46 100644 --- a/translations/content/pl/datetime/date-formatting.yaml +++ b/translations/content/pl/datetime/date-formatting.yaml @@ -5,7 +5,7 @@ summary: Formatuj daty przez niezmienny i bezpieczny wątkowo DateTimeFormatter. explanation: DateTimeFormatter jest niemutowalny i bezpieczny wątkowo, w przeciwieństwie do SimpleDateFormat. Możesz przechowywać go jako stałą i współdzielić. Dla typowych formatów dostępne są gotowe formattery, np. ISO_LOCAL_DATE. whyModernWins: - icon: 🛡️ - title: Bezpieczeństwo wątkowe + title: Wątków bezpieczeństwo desc: Możesz współdzielić formattery między wątkami bez synchronizacji. - icon: 📋 title: Wbudowane formaty From fbc36840946c551ceb9672d67339297d14b13c7b Mon Sep 17 00:00:00 2001 From: Artur Skowronski Date: Fri, 27 Feb 2026 13:37:30 +0100 Subject: [PATCH 11/28] chore(i18n): keep pragmatic Polish wording with natural anglicisms --- translations/content/pl/language/type-inference-with-var.yaml | 2 +- translations/strings/pl.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/translations/content/pl/language/type-inference-with-var.yaml b/translations/content/pl/language/type-inference-with-var.yaml index 122d61c..743186c 100644 --- a/translations/content/pl/language/type-inference-with-var.yaml +++ b/translations/content/pl/language/type-inference-with-var.yaml @@ -1,7 +1,7 @@ title: Inferencja typów z var oldApproach: Jawne typy modernApproach: Słowo kluczowe var -summary: Używaj var do inferencji typów zmiennych lokalnych, mniej szumu i taka sama kontrola typów. +summary: Używaj var do inferencji typów zmiennych lokalnych, mniej szumu i to samo bezpieczeństwo typów. explanation: Od Java 10 kompilator wywnioskuje typ zmiennej lokalnej na podstawie prawej strony przypisania. To ogranicza wizualny szum bez utraty bezpieczeństwa typów. Używaj var, gdy typ jest oczywisty z kontekstu. whyModernWins: - icon: ⚡ diff --git a/translations/strings/pl.yaml b/translations/strings/pl.yaml index ba66c2b..e97cc1a 100644 --- a/translations/strings/pl.yaml +++ b/translations/strings/pl.yaml @@ -60,7 +60,7 @@ stats: modernPatterns: Nowoczesne wzorce jdkVersions: Obsługiwane wersje JDK categories: Kategorie - linesOfPython: Linie Pythona wymagane + linesOfPython: Wymagane linie Pythona footer: tagline: Java ewoluowała. Twój kod też może. madeWith: Stworzone z ❤️ przez From 331808504eadee8861fb81ca0ddf456ba2ca094b Mon Sep 17 00:00:00 2001 From: Bruno Borges Date: Fri, 27 Feb 2026 09:10:39 -0500 Subject: [PATCH 12/28] Update French tagline for clarity --- translations/strings/fr.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/translations/strings/fr.yaml b/translations/strings/fr.yaml index 3e48a9f..1f1a0fb 100644 --- a/translations/strings/fr.yaml +++ b/translations/strings/fr.yaml @@ -1,6 +1,6 @@ site: title: java.evolved - tagline: Java a évolué. Votre code aussi peut. + tagline: Java a évolué. Votre code peut aussi. tagline_line1: Java a évolué. tagline_line2: Votre code aussi peut. description: Une collection de snippets Java modernes. Chaque ancien pattern Java From a7b7e6300cf2270646d4b18864708ff55e3a6050 Mon Sep 17 00:00:00 2001 From: Bruno Borges Date: Fri, 27 Feb 2026 09:12:57 -0500 Subject: [PATCH 13/28] Fix French translation for tagline consistency --- translations/strings/fr.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/translations/strings/fr.yaml b/translations/strings/fr.yaml index 1f1a0fb..df46ae7 100644 --- a/translations/strings/fr.yaml +++ b/translations/strings/fr.yaml @@ -2,7 +2,7 @@ site: title: java.evolved tagline: Java a évolué. Votre code peut aussi. tagline_line1: Java a évolué. - tagline_line2: Votre code aussi peut. + tagline_line2: Votre code peut aussi. description: Une collection de snippets Java modernes. Chaque ancien pattern Java à côté de son remplacement moderne et propre — côte à côte. heroSnippetCount: ✦ {{snippetCount}} patterns modernes · Java 8 → Java 25 @@ -64,7 +64,7 @@ stats: categories: Catégories linesOfPython: Lignes de Python Requises footer: - tagline: Java a évolué. Votre code aussi peut. + tagline: Java a évolué. Votre code peut aussi. madeWith: Fait avec ❤️ par and: et inspiredBy: Inspiré par From f290197b23662efacfea21daccb37b0af3c9ae9a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:20:57 +0000 Subject: [PATCH 14/28] Initial plan From fae0e363ec2e38b9b7db0d18fd9f32afe054d071 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:21:48 +0000 Subject: [PATCH 15/28] Initial plan From 0d19451909e2eccac521716a49b458185d4a6068 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:26:44 +0000 Subject: [PATCH 16/28] feat: replace System.out.println with IO.println in modern code slugs Co-authored-by: brunoborges <129743+brunoborges@users.noreply.github.com> --- content/collections/reverse-list-iteration.yaml | 2 +- content/concurrency/completablefuture-chaining.yaml | 2 +- content/concurrency/process-api.yaml | 4 ++-- content/concurrency/virtual-threads.yaml | 2 +- content/language/default-interface-methods.yaml | 2 +- content/language/pattern-matching-instanceof.yaml | 2 +- content/language/private-interface-methods.yaml | 4 ++-- content/language/record-patterns.yaml | 2 +- content/streams/stream-iterate-predicate.yaml | 2 +- content/strings/string-lines.yaml | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/content/collections/reverse-list-iteration.yaml b/content/collections/reverse-list-iteration.yaml index 5def7d7..4c850f1 100644 --- a/content/collections/reverse-list-iteration.yaml +++ b/content/collections/reverse-list-iteration.yaml @@ -18,7 +18,7 @@ oldCode: |- } modernCode: |- for (String element : list.reversed()) { - System.out.println(element); + IO.println(element); } summary: "Iterate over a list in reverse order with a clean for-each loop." explanation: "The reversed() method from SequencedCollection returns a reverse-ordered\ diff --git a/content/concurrency/completablefuture-chaining.yaml b/content/concurrency/completablefuture-chaining.yaml index 833d4d2..5dbae6f 100644 --- a/content/concurrency/completablefuture-chaining.yaml +++ b/content/concurrency/completablefuture-chaining.yaml @@ -19,7 +19,7 @@ modernCode: |- this::fetchData ) .thenApply(this::transform) - .thenAccept(System.out::println); + .thenAccept(IO::println); summary: "Chain async operations without blocking, using CompletableFuture." explanation: "CompletableFuture enables non-blocking async pipelines. Chain operations\ \ with thenApply, thenCompose, thenAccept. Handle errors with exceptionally(). Combine\ diff --git a/content/concurrency/process-api.yaml b/content/concurrency/process-api.yaml index 6ba3508..4689b9e 100644 --- a/content/concurrency/process-api.yaml +++ b/content/concurrency/process-api.yaml @@ -20,9 +20,9 @@ modernCode: |- ProcessHandle.current(); long pid = ph.pid(); ph.info().command() - .ifPresent(System.out::println); + .ifPresent(IO::println); ph.children().forEach( - c -> System.out.println(c.pid())); + c -> IO.println(c.pid())); summary: "Inspect and manage OS processes with ProcessHandle." explanation: "ProcessHandle provides PIDs, process info (command, arguments, start\ \ time, CPU usage), parent/child relationships, and process destruction. No more\ diff --git a/content/concurrency/virtual-threads.yaml b/content/concurrency/virtual-threads.yaml index 0c8b4f5..3e5e6ab 100644 --- a/content/concurrency/virtual-threads.yaml +++ b/content/concurrency/virtual-threads.yaml @@ -17,7 +17,7 @@ oldCode: |- thread.join(); modernCode: |- Thread.startVirtualThread(() -> { - System.out.println("hello"); + IO.println("hello"); }).join(); summary: "Create millions of lightweight virtual threads instead of heavy OS threads." explanation: "Virtual threads are lightweight threads managed by the JVM, not the\ diff --git a/content/language/default-interface-methods.yaml b/content/language/default-interface-methods.yaml index 5b00d29..e5b4b56 100644 --- a/content/language/default-interface-methods.yaml +++ b/content/language/default-interface-methods.yaml @@ -25,7 +25,7 @@ oldCode: |- modernCode: |- public interface Logger { default void log(String msg) { - System.out.println( + IO.println( timestamp() + ": " + msg); } String timestamp(); diff --git a/content/language/pattern-matching-instanceof.yaml b/content/language/pattern-matching-instanceof.yaml index 53aaf0e..d4306b7 100644 --- a/content/language/pattern-matching-instanceof.yaml +++ b/content/language/pattern-matching-instanceof.yaml @@ -16,7 +16,7 @@ oldCode: |- } modernCode: |- if (obj instanceof String s) { - System.out.println(s.length()); + IO.println(s.length()); } summary: "Combine type check and cast in one step with pattern matching." explanation: "Pattern matching for instanceof eliminates the redundant cast after\ diff --git a/content/language/private-interface-methods.yaml b/content/language/private-interface-methods.yaml index db6be10..2730682 100644 --- a/content/language/private-interface-methods.yaml +++ b/content/language/private-interface-methods.yaml @@ -26,10 +26,10 @@ modernCode: |- return "[" + lvl + "] " + timestamp() + msg; } default void logInfo(String msg) { - System.out.println(format("INFO", msg)); + IO.println(format("INFO", msg)); } default void logWarn(String msg) { - System.out.println(format("WARN", msg)); + IO.println(format("WARN", msg)); } } summary: "Extract shared logic in interfaces using private methods." diff --git a/content/language/record-patterns.yaml b/content/language/record-patterns.yaml index 1f72124..55a5e1b 100644 --- a/content/language/record-patterns.yaml +++ b/content/language/record-patterns.yaml @@ -18,7 +18,7 @@ oldCode: |- } modernCode: |- if (obj instanceof Point(int x, int y)) { - System.out.println(x + y); + IO.println(x + y); } summary: "Destructure records directly in patterns — extract fields in one step." explanation: "Record patterns let you decompose a record's components directly in\ diff --git a/content/streams/stream-iterate-predicate.yaml b/content/streams/stream-iterate-predicate.yaml index 39f42db..a17deaf 100644 --- a/content/streams/stream-iterate-predicate.yaml +++ b/content/streams/stream-iterate-predicate.yaml @@ -19,7 +19,7 @@ modernCode: |- 1, n -> n < 1000, n -> n * 2 - ).forEach(System.out::println); + ).forEach(IO::println); // stops when n >= 1000 summary: "Use a predicate to stop iteration — like a for-loop in stream form." explanation: "The three-argument Stream.iterate(seed, hasNext, next) works like a\ diff --git a/content/strings/string-lines.yaml b/content/strings/string-lines.yaml index 33ff54b..cc08d71 100644 --- a/content/strings/string-lines.yaml +++ b/content/strings/string-lines.yaml @@ -17,7 +17,7 @@ oldCode: |- } modernCode: |- String text = "one\ntwo\nthree"; - text.lines().forEach(System.out::println); + text.lines().forEach(IO::println); summary: "Use String.lines() to split text into a stream of lines without regex overhead." explanation: "String.lines() returns a Stream of lines split by \\n, \\r,\ \ or \\r\\n. It is lazier and more efficient than split(), avoids regex compilation,\ From 0a827e55be8d73d85db60dec9aca0a1104d80711 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:27:53 +0000 Subject: [PATCH 17/28] Add Turkish (tr) translations for collections and concurrency patterns Translate 10 collections and 10 concurrency pattern YAML files to Turkish. - translations/content/tr/collections/collectors-teeing.yaml - translations/content/tr/collections/copying-collections-immutably.yaml - translations/content/tr/collections/immutable-list-creation.yaml - translations/content/tr/collections/immutable-map-creation.yaml - translations/content/tr/collections/immutable-set-creation.yaml - translations/content/tr/collections/map-entry-factory.yaml - translations/content/tr/collections/reverse-list-iteration.yaml - translations/content/tr/collections/sequenced-collections.yaml - translations/content/tr/collections/stream-toarray-typed.yaml - translations/content/tr/collections/unmodifiable-collectors.yaml - translations/content/tr/concurrency/completablefuture-chaining.yaml - translations/content/tr/concurrency/concurrent-http-virtual.yaml - translations/content/tr/concurrency/executor-try-with-resources.yaml - translations/content/tr/concurrency/lock-free-lazy-init.yaml - translations/content/tr/concurrency/process-api.yaml - translations/content/tr/concurrency/scoped-values.yaml - translations/content/tr/concurrency/stable-values.yaml - translations/content/tr/concurrency/structured-concurrency.yaml - translations/content/tr/concurrency/thread-sleep-duration.yaml - translations/content/tr/concurrency/virtual-threads.yaml Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../tr/collections/collectors-teeing.yaml | 18 ++++++++++++++++++ .../copying-collections-immutably.yaml | 18 ++++++++++++++++++ .../collections/immutable-list-creation.yaml | 18 ++++++++++++++++++ .../tr/collections/immutable-map-creation.yaml | 18 ++++++++++++++++++ .../tr/collections/immutable-set-creation.yaml | 18 ++++++++++++++++++ .../tr/collections/map-entry-factory.yaml | 18 ++++++++++++++++++ .../tr/collections/reverse-list-iteration.yaml | 18 ++++++++++++++++++ .../tr/collections/sequenced-collections.yaml | 18 ++++++++++++++++++ .../tr/collections/stream-toarray-typed.yaml | 18 ++++++++++++++++++ .../collections/unmodifiable-collectors.yaml | 18 ++++++++++++++++++ .../completablefuture-chaining.yaml | 18 ++++++++++++++++++ .../concurrency/concurrent-http-virtual.yaml | 18 ++++++++++++++++++ .../executor-try-with-resources.yaml | 18 ++++++++++++++++++ .../tr/concurrency/lock-free-lazy-init.yaml | 18 ++++++++++++++++++ .../content/tr/concurrency/process-api.yaml | 18 ++++++++++++++++++ .../content/tr/concurrency/scoped-values.yaml | 18 ++++++++++++++++++ .../content/tr/concurrency/stable-values.yaml | 18 ++++++++++++++++++ .../tr/concurrency/structured-concurrency.yaml | 18 ++++++++++++++++++ .../tr/concurrency/thread-sleep-duration.yaml | 18 ++++++++++++++++++ .../tr/concurrency/virtual-threads.yaml | 18 ++++++++++++++++++ 20 files changed, 360 insertions(+) create mode 100644 translations/content/tr/collections/collectors-teeing.yaml create mode 100644 translations/content/tr/collections/copying-collections-immutably.yaml create mode 100644 translations/content/tr/collections/immutable-list-creation.yaml create mode 100644 translations/content/tr/collections/immutable-map-creation.yaml create mode 100644 translations/content/tr/collections/immutable-set-creation.yaml create mode 100644 translations/content/tr/collections/map-entry-factory.yaml create mode 100644 translations/content/tr/collections/reverse-list-iteration.yaml create mode 100644 translations/content/tr/collections/sequenced-collections.yaml create mode 100644 translations/content/tr/collections/stream-toarray-typed.yaml create mode 100644 translations/content/tr/collections/unmodifiable-collectors.yaml create mode 100644 translations/content/tr/concurrency/completablefuture-chaining.yaml create mode 100644 translations/content/tr/concurrency/concurrent-http-virtual.yaml create mode 100644 translations/content/tr/concurrency/executor-try-with-resources.yaml create mode 100644 translations/content/tr/concurrency/lock-free-lazy-init.yaml create mode 100644 translations/content/tr/concurrency/process-api.yaml create mode 100644 translations/content/tr/concurrency/scoped-values.yaml create mode 100644 translations/content/tr/concurrency/stable-values.yaml create mode 100644 translations/content/tr/concurrency/structured-concurrency.yaml create mode 100644 translations/content/tr/concurrency/thread-sleep-duration.yaml create mode 100644 translations/content/tr/concurrency/virtual-threads.yaml diff --git a/translations/content/tr/collections/collectors-teeing.yaml b/translations/content/tr/collections/collectors-teeing.yaml new file mode 100644 index 0000000..e9b8400 --- /dev/null +++ b/translations/content/tr/collections/collectors-teeing.yaml @@ -0,0 +1,18 @@ +--- +title: Collectors.teeing() +oldApproach: İki Geçiş +modernApproach: teeing() +summary: "Tek bir stream geçişinde iki toplama işlemi gerçekleştirin." +explanation: "Collectors.teeing(), her elemanı iki alt collector'a gönderir ve sonuçları birleştirir. Bu sayede veriyi iki kez akıtmaktan veya değiştirilebilir bir biriktirici kullanmaktan kaçınılır." +whyModernWins: +- icon: "⚡" + title: "Tek geçiş" + desc: "Stream'i iki yerine bir kez işleyin." +- icon: "🧩" + title: "Birleştirilebilir" + desc: "Herhangi iki collector'ı birleştirme fonksiyonuyla bir araya getirin." +- icon: "🔒" + title: "Değişmez sonuç" + desc: "Doğrudan bir record veya değer nesnesine birleştirin." +support: + description: JDK 12'den itibaren geniş çapta kullanılabilir (Mart 2019) diff --git a/translations/content/tr/collections/copying-collections-immutably.yaml b/translations/content/tr/collections/copying-collections-immutably.yaml new file mode 100644 index 0000000..a38954b --- /dev/null +++ b/translations/content/tr/collections/copying-collections-immutably.yaml @@ -0,0 +1,18 @@ +--- +title: Koleksiyonları değişmez biçimde kopyalama +oldApproach: Elle Kopyalama + Sarmalama +modernApproach: List.copyOf() +summary: "Herhangi bir koleksiyonun değişmez kopyasını tek çağrıyla oluşturun." +explanation: "List.copyOf(), Set.copyOf() ve Map.copyOf() mevcut koleksiyonların değişmez anlık görüntülerini oluşturur. Kaynak zaten değişmez bir koleksiyonsa kopyalama yapılmaz." +whyModernWins: +- icon: "⚡" + title: "Akıllı kopyalama" + desc: "Kaynak zaten değişmezse kopyalamayı atlar." +- icon: "📏" + title: "Tek çağrı" + desc: "Elle ArrayList oluşturma ve sarmalama gerekmez." +- icon: "🛡️" + title: "Savunmacı kopya" + desc: "Orijinaldeki değişiklikler kopyayı etkilemez." +support: + description: JDK 10'dan itibaren geniş çapta kullanılabilir (Mart 2018) diff --git a/translations/content/tr/collections/immutable-list-creation.yaml b/translations/content/tr/collections/immutable-list-creation.yaml new file mode 100644 index 0000000..bb971b9 --- /dev/null +++ b/translations/content/tr/collections/immutable-list-creation.yaml @@ -0,0 +1,18 @@ +--- +title: Değişmez liste oluşturma +oldApproach: Ayrıntılı Sarmalama +modernApproach: List.of() +summary: "Değişmez listeleri tek ve temiz bir ifadeyle oluşturun." +explanation: "List.of(), sarmalama veya savunmacı kopya gerektirmeksizin gerçek anlamda değişmez bir liste oluşturur. Null düşman yapısıyla (null öğeleri reddeder) yapısal olarak değişmezdir. Eski yöntem üç iç içe çağrı gerektiriyordu." +whyModernWins: +- icon: "📏" + title: "Tek çağrı" + desc: "Üç iç içe çağrıyı tek bir factory metoduyla değiştirin." +- icon: "🔒" + title: "Gerçekten değişmez" + desc: "Sadece bir sarmalayıcı değil — listenin kendisi değişmezdir." +- icon: "🛡️" + title: "Null-güvenli" + desc: "Oluşturma sırasında null öğeleri reddeder, hızlı hata verir." +support: + description: JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017) diff --git a/translations/content/tr/collections/immutable-map-creation.yaml b/translations/content/tr/collections/immutable-map-creation.yaml new file mode 100644 index 0000000..c6c2e78 --- /dev/null +++ b/translations/content/tr/collections/immutable-map-creation.yaml @@ -0,0 +1,18 @@ +--- +title: Değişmez map oluşturma +oldApproach: Map Builder Kalıbı +modernApproach: Map.of() +summary: "Builder kullanmadan satır içi değişmez map'ler oluşturun." +explanation: "Map.of(), anahtar-değer çiftlerini satır içinde alır ve değişmez bir map döndürür. 10'dan fazla giriş için Map.entry() çiftleriyle birlikte Map.ofEntries() kullanın." +whyModernWins: +- icon: "📏" + title: "Satır içi oluşturma" + desc: "Geçici değiştirilebilir map gerekmez." +- icon: "🔒" + title: "Değişmez sonuç" + desc: "Map oluşturulduktan sonra değiştirilemez." +- icon: "🚫" + title: "Null anahtar/değer yok" + desc: "Null girişler anında reddedilir." +support: + description: JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017) diff --git a/translations/content/tr/collections/immutable-set-creation.yaml b/translations/content/tr/collections/immutable-set-creation.yaml new file mode 100644 index 0000000..4cafccc --- /dev/null +++ b/translations/content/tr/collections/immutable-set-creation.yaml @@ -0,0 +1,18 @@ +--- +title: Değişmez set oluşturma +oldApproach: Ayrıntılı Sarmalama +modernApproach: Set.of() +summary: "Tek bir factory çağrısıyla değişmez set'ler oluşturun." +explanation: "Set.of(), oluşturma sırasında null'ları ve yinelenen öğeleri reddeden gerçek anlamda değişmez bir set oluşturur. Artık değiştirilebilir set'leri sarmalamanıza gerek yok." +whyModernWins: +- icon: "📏" + title: "Kısa ve öz" + desc: "Üç iç içe çağrı yerine tek satır." +- icon: "🚫" + title: "Tekrarlananları algılar" + desc: "Yanlışlıkla yinelenen öğeler geçirilirse hata fırlatır." +- icon: "🔒" + title: "Değişmez" + desc: "Oluşturulduktan sonra ekleme/çıkarma yapılamaz." +support: + description: JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017) diff --git a/translations/content/tr/collections/map-entry-factory.yaml b/translations/content/tr/collections/map-entry-factory.yaml new file mode 100644 index 0000000..7f07571 --- /dev/null +++ b/translations/content/tr/collections/map-entry-factory.yaml @@ -0,0 +1,18 @@ +--- +title: Map.entry() factory +oldApproach: SimpleEntry +modernApproach: Map.entry() +summary: "Map girişlerini temiz bir factory metoduyla oluşturun." +explanation: "Map.entry(), ayrıntılı AbstractMap.SimpleEntry yapıcısının yerini alır. Değişmez bir giriş döndürür; bu da onu Map.ofEntries() ve stream işlemleri için ideal kılar." +whyModernWins: +- icon: "📏" + title: "Kısa ve öz" + desc: "Daha net bir niyetle üç satır yerine tek satır." +- icon: "🔒" + title: "Değişmez" + desc: "Döndürülen giriş değiştirilemez." +- icon: "🧩" + title: "Birleştirilebilir" + desc: "Büyük map'ler için Map.ofEntries() ile mükemmel çalışır." +support: + description: JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017) diff --git a/translations/content/tr/collections/reverse-list-iteration.yaml b/translations/content/tr/collections/reverse-list-iteration.yaml new file mode 100644 index 0000000..a2653b2 --- /dev/null +++ b/translations/content/tr/collections/reverse-list-iteration.yaml @@ -0,0 +1,18 @@ +--- +title: Ters liste yineleme +oldApproach: Elle ListIterator +modernApproach: reversed() +summary: "Bir liste üzerinde temiz bir for-each döngüsüyle ters sırada yineleyin." +explanation: "SequencedCollection'dan gelen reversed() metodu, listenin ters sıralı bir görünümünü döndürür. Bu görünüm orijinal listenin arkasına dayandığından kopyalama yapılmaz. Geliştirilmiş for döngüsü sözdizimi, ters yinelemeyi ileri yineleme kadar okunabilir kılar." +whyModernWins: +- icon: "📖" + title: "Doğal sözdizimi" + desc: "Ayrıntılı ListIterator yerine geliştirilmiş for döngüsü." +- icon: "⚡" + title: "Kopyalama yok" + desc: "reversed() bir görünüm döndürür — performans yükü yoktur." +- icon: "🧩" + title: "Tutarlı API" + desc: "List, Deque, SortedSet üzerinde tekdüze çalışır." +support: + description: JDK 21 LTS'den itibaren geniş çapta kullanılabilir (Eylül 2023) diff --git a/translations/content/tr/collections/sequenced-collections.yaml b/translations/content/tr/collections/sequenced-collections.yaml new file mode 100644 index 0000000..ed16282 --- /dev/null +++ b/translations/content/tr/collections/sequenced-collections.yaml @@ -0,0 +1,18 @@ +--- +title: Sıralı koleksiyonlar +oldApproach: İndeks Aritmetiği +modernApproach: getFirst/getLast +summary: "Temiz API metodlarıyla ilk/son öğelere ve ters görünümlere erişin." +explanation: "SequencedCollection, List, Deque, SortedSet ve LinkedHashSet'e getFirst(), getLast(), reversed(), addFirst(), addLast() ekler. Artık size-1 aritmetiğine veya elle ters yinelemeye gerek yok." +whyModernWins: +- icon: "📖" + title: "Kendini belgeleyen" + desc: "getLast(), get(size()-1) ifadesinden çok daha açıktır." +- icon: "🔄" + title: "Ters görünüm" + desc: "reversed() bir görünüm verir — kopyalama gerekmez." +- icon: "🧩" + title: "Tekdüze API" + desc: "List, Deque, SortedSet üzerinde aynı şekilde çalışır." +support: + description: JDK 21 LTS'den itibaren geniş çapta kullanılabilir (Eylül 2023) diff --git a/translations/content/tr/collections/stream-toarray-typed.yaml b/translations/content/tr/collections/stream-toarray-typed.yaml new file mode 100644 index 0000000..6486725 --- /dev/null +++ b/translations/content/tr/collections/stream-toarray-typed.yaml @@ -0,0 +1,18 @@ +--- +title: Tiplendirilmiş stream toArray +oldApproach: Elle Dizi Kopyalama +modernApproach: toArray(generator) +summary: "Stream'leri metot referansıyla tiplendirilmiş dizilere dönüştürün." +explanation: "toArray(IntFunction) metodu, bir stream'den düzgün tiplendirilmiş bir dizi oluşturur. Üretici (String[]::new), stream'e hangi türde dizi oluşturacağını söyler." +whyModernWins: +- icon: "🎯" + title: "Tip güvenli" + desc: "Object[] dönüşümü yok — dizi türü doğrudur." +- icon: "🔗" + title: "Zincirlenebilir" + desc: "Herhangi bir stream hattının sonunda çalışır." +- icon: "📏" + title: "Kısa ve öz" + desc: "Tek ifade elle yapılan döngünün yerini alır." +support: + description: JDK 8'den itibaren geniş çapta kullanılabilir (Mart 2014) diff --git a/translations/content/tr/collections/unmodifiable-collectors.yaml b/translations/content/tr/collections/unmodifiable-collectors.yaml new file mode 100644 index 0000000..8c36434 --- /dev/null +++ b/translations/content/tr/collections/unmodifiable-collectors.yaml @@ -0,0 +1,18 @@ +--- +title: Değiştirilemez collector'lar +oldApproach: collectingAndThen +modernApproach: stream.toList() +summary: "stream.toList() ile doğrudan değiştirilemez bir listeye toplayın." +explanation: "Java 10, ayrıntılı collectingAndThen sarmalayıcısının yerini almak için toUnmodifiableList(), toUnmodifiableSet() ve toUnmodifiableMap() ekledi. Listeler için Java 16'nın stream.toList() yöntemi daha da basit bir alternatif sunar — hiç collect() çağrısına gerek yoktur. Diğer koleksiyon türleri için toUnmodifiableSet() ve toUnmodifiableMap() kullanın." +whyModernWins: +- icon: "📏" + title: "En kısa yol" + desc: "stream.toList() hiç collect() veya Collectors import gerektirmez." +- icon: "🔒" + title: "Değişmez" + desc: "Sonuç değiştirilemez — yanlışlıkla mutasyon olmaz." +- icon: "📖" + title: "Okunabilir" + desc: "Herhangi bir stream hattının terminal adımı olarak doğal okunur." +support: + description: JDK 16'dan itibaren geniş çapta kullanılabilir (Mart 2021) diff --git a/translations/content/tr/concurrency/completablefuture-chaining.yaml b/translations/content/tr/concurrency/completablefuture-chaining.yaml new file mode 100644 index 0000000..a584ddc --- /dev/null +++ b/translations/content/tr/concurrency/completablefuture-chaining.yaml @@ -0,0 +1,18 @@ +--- +title: CompletableFuture zinciri +oldApproach: Bloklayan Future.get() +modernApproach: CompletableFuture +summary: "CompletableFuture kullanarak bloklamadan asenkron işlemleri zincirleme." +explanation: "CompletableFuture, bloklamayan asenkron hatlar sağlar. İşlemleri thenApply, thenCompose, thenAccept ile zincirleyin. Hataları exceptionally() ile işleyin. Birden fazla future'ı allOf/anyOf ile birleştirin." +whyModernWins: +- icon: "🔗" + title: "Zincirlenebilir" + desc: "Asenkron adımları okunabilir bir hatta birleştirin." +- icon: "🚫" + title: "Bloklama yok" + desc: "Hiçbir iş parçacığı sonuçları beklemek için boşta durmaz." +- icon: "🛡️" + title: "Hata işleme" + desc: "exceptionally() ve handle() ile temiz hata kurtarma." +support: + description: JDK 8'den itibaren geniş çapta kullanılabilir (Mart 2014) diff --git a/translations/content/tr/concurrency/concurrent-http-virtual.yaml b/translations/content/tr/concurrency/concurrent-http-virtual.yaml new file mode 100644 index 0000000..dd82b01 --- /dev/null +++ b/translations/content/tr/concurrency/concurrent-http-virtual.yaml @@ -0,0 +1,18 @@ +--- +title: Sanal iş parçacıklarıyla eşzamanlı HTTP +oldApproach: İş Parçacığı Havuzu + URLConnection +modernApproach: Sanal İş Parçacıkları + HttpClient +summary: "Sanal iş parçacıkları ve HttpClient ile birçok URL'yi eşzamanlı getirin." +explanation: "Sanal iş parçacıkları, her HTTP isteği için bir iş parçacığı oluşturmayı pratik hale getirir. HttpClient ile birleştirildiğinde, karmaşık asenkron geri arama kalıplarının yerini ölçeklenen basit bloklama koduyla alır." +whyModernWins: +- icon: "♾️" + title: "İstek başına iş parçacığı" + desc: "Havuz boyutlandırması yok — URL başına bir sanal iş parçacığı." +- icon: "📖" + title: "Basit kod" + desc: "Anlaşılır bloklama kodu yazın." +- icon: "⚡" + title: "Yüksek verim" + desc: "Minimum kaynak kullanımıyla binlerce eşzamanlı istek." +support: + description: JDK 21 LTS'den itibaren geniş çapta kullanılabilir (Eylül 2023) diff --git a/translations/content/tr/concurrency/executor-try-with-resources.yaml b/translations/content/tr/concurrency/executor-try-with-resources.yaml new file mode 100644 index 0000000..c82c7cc --- /dev/null +++ b/translations/content/tr/concurrency/executor-try-with-resources.yaml @@ -0,0 +1,18 @@ +--- +title: ExecutorService otomatik kapanma +oldApproach: Elle Kapatma +modernApproach: try-with-resources +summary: "Otomatik executor kapatma için try-with-resources kullanın." +explanation: "Java 19'dan itibaren ExecutorService, AutoCloseable arayüzünü uygular. close() metodu shutdown() çağırır ve görevlerin tamamlanmasını bekler. Artık elle try/finally kapatma kalıplarına gerek yok." +whyModernWins: +- icon: "🧹" + title: "Otomatik temizleme" + desc: "Blok çıkışında kapatma otomatik gerçekleşir." +- icon: "🛡️" + title: "Sızıntı yok" + desc: "İstisnalar oluşsa bile executor her zaman kapanır." +- icon: "📖" + title: "Tanıdık kalıp" + desc: "Dosyalar ve bağlantılar için kullanılan aynı try-with-resources." +support: + description: JDK 19'dan itibaren geniş çapta kullanılabilir (Eylül 2022) diff --git a/translations/content/tr/concurrency/lock-free-lazy-init.yaml b/translations/content/tr/concurrency/lock-free-lazy-init.yaml new file mode 100644 index 0000000..f8d5b12 --- /dev/null +++ b/translations/content/tr/concurrency/lock-free-lazy-init.yaml @@ -0,0 +1,18 @@ +--- +title: Kilitlenmesiz tembel başlatma +oldApproach: synchronized + volatile +modernApproach: StableValue +summary: "Tembel singleton'lar için çift kontrollü kilitleme yerine StableValue kullanın." +explanation: "StableValue, doğru iş parçacığı güvenliğiyle tembel başlatma kalıbını kapsüller. JVM, başlatma sonrasında okuma yolunu optimize edebilir; bu da onu volatile okumalardan daha hızlı yapabilir." +whyModernWins: +- icon: "🧹" + title: "Şablonsuz kod yok" + desc: "volatile, synchronized veya çift null kontrolü yok." +- icon: "⚡" + title: "Daha hızlı okumalar" + desc: "JVM başlatma sonrasında değeri sabit katlamaya alabilir." +- icon: "✅" + title: "Kanıtlanmış doğruluk" + desc: "İnce sıralama hataları yok — JVM halleder." +support: + description: "JDK 25'te önizleme (JEP 502, StableValue). --enable-preview gerektirir." diff --git a/translations/content/tr/concurrency/process-api.yaml b/translations/content/tr/concurrency/process-api.yaml new file mode 100644 index 0000000..e8fb1b3 --- /dev/null +++ b/translations/content/tr/concurrency/process-api.yaml @@ -0,0 +1,18 @@ +--- +title: Modern Process API +oldApproach: Runtime.exec() +modernApproach: ProcessHandle +summary: "ProcessHandle ile işletim sistemi süreçlerini inceleyin ve yönetin." +explanation: "ProcessHandle; PID'leri, süreç bilgilerini (komut, argümanlar, başlangıç zamanı, CPU kullanımı), üst/alt ilişkilerini ve süreç sonlandırmayı sağlar. Artık belgelenmemiş Process iç kısımlarına gerek yok." +whyModernWins: +- icon: "🔍" + title: "Tam bilgi" + desc: "PID, komut, argümanlar, başlangıç zamanı, CPU kullanımına erişin." +- icon: "🌳" + title: "Süreç ağacı" + desc: "Üst, alt ve torun süreçlerde gezinin." +- icon: "📊" + title: "İzleme" + desc: "onExit() asenkron izleme için bir CompletableFuture döndürür." +support: + description: JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017) diff --git a/translations/content/tr/concurrency/scoped-values.yaml b/translations/content/tr/concurrency/scoped-values.yaml new file mode 100644 index 0000000..5f02015 --- /dev/null +++ b/translations/content/tr/concurrency/scoped-values.yaml @@ -0,0 +1,18 @@ +--- +title: Kapsamlı değerler +oldApproach: ThreadLocal +modernApproach: ScopedValue +summary: "ThreadLocal tuzakları olmadan çağrı yığınları arasında güvenle veri paylaşın." +explanation: "ScopedValue; değiştirilemez, miras alınabilir, kapsam sınırlı bağlam sağlar. ThreadLocal'dan farklı olarak kapsamlı değerler otomatik temizlenir, sanal iş parçacıklarıyla çalışır ve çağrılanlar tarafından değiştirilemez." +whyModernWins: +- icon: "🔒" + title: "Değiştirilemez" + desc: "Çağrılanlar kapsamlı değeri okuyabilir ama asla değiştiremez." +- icon: "🧹" + title: "Otomatik temizleme" + desc: "Elle remove() gerekmez — değer blokla sınırlıdır." +- icon: "⚡" + title: "Sanal iş parçacığı güvenli" + desc: "Milyonlarca sanal iş parçacığıyla verimli çalışır." +support: + description: "JDK 25 LTS'de kesinleşti (JEP 506, Eylül 2025)." diff --git a/translations/content/tr/concurrency/stable-values.yaml b/translations/content/tr/concurrency/stable-values.yaml new file mode 100644 index 0000000..310a6f9 --- /dev/null +++ b/translations/content/tr/concurrency/stable-values.yaml @@ -0,0 +1,18 @@ +--- +title: Kararlı değerler +oldApproach: Çift Kontrollü Kilitleme +modernApproach: StableValue +summary: "volatile veya synchronized olmadan iş parçacığı güvenli tembel başlatma." +explanation: "StableValue, yerleşik iş parçacığı güvenliğiyle tembel başlatılmış, değiştirilemez bir değer sağlar. Çift kontrollü kilitleme yok, volatile alan yok, synchronized blok yok. JVM başlatma sonrasında okuma yolunu bile optimize edebilir." +whyModernWins: +- icon: "🧹" + title: "Sıfır şablonsuz kod" + desc: "volatile, synchronized veya null kontrolleri yok." +- icon: "⚡" + title: "JVM-optimize" + desc: "JVM başlatma sonrasında değeri katlayabilir." +- icon: "🛡️" + title: "Bir kez garantili" + desc: "Sağlayıcı, çakışma altında bile yalnızca bir kez çalışır." +support: + description: "JDK 25'te önizleme (JEP 502). --enable-preview gerektirir." diff --git a/translations/content/tr/concurrency/structured-concurrency.yaml b/translations/content/tr/concurrency/structured-concurrency.yaml new file mode 100644 index 0000000..f9f093d --- /dev/null +++ b/translations/content/tr/concurrency/structured-concurrency.yaml @@ -0,0 +1,18 @@ +--- +title: Yapılandırılmış eşzamanlılık +oldApproach: Elle İş Parçacığı Yaşam Döngüsü +modernApproach: StructuredTaskScope +summary: "Eşzamanlı görev ömürlerini tek bir iş birimi olarak yönetin." +explanation: "Yapılandırılmış eşzamanlılık, bir grup eşzamanlı görevi tek bir işlem olarak ele alır. Herhangi bir alt görev başarısız olursa diğerleri iptal edilir. Kapsam, iş parçacığı sızıntısı olmadığını garanti eder ve açık üst-alt ilişkileri sunar." +whyModernWins: +- icon: "🛡️" + title: "İş parçacığı sızıntısı yok" + desc: "Tüm çatallanmış görevler kapsam kapanmadan önce tamamlanır." +- icon: "⚡" + title: "Hızlı hata" + desc: "ShutdownOnFailure, biri başarısız olursa kardeş görevleri iptal eder." +- icon: "📐" + title: "Açık yapı" + desc: "Görev ömrü koddaki sözcüksel kapsamla eşleşir." +support: + description: "JDK 25'te önizleme (beşinci önizleme, JEP 505). --enable-preview gerektirir." diff --git a/translations/content/tr/concurrency/thread-sleep-duration.yaml b/translations/content/tr/concurrency/thread-sleep-duration.yaml new file mode 100644 index 0000000..c66cdf3 --- /dev/null +++ b/translations/content/tr/concurrency/thread-sleep-duration.yaml @@ -0,0 +1,18 @@ +--- +title: Duration ile Thread.sleep +oldApproach: Milisaniye +modernApproach: Duration +summary: "Kendini belgeleyen zaman değerleri için Duration kullanın." +explanation: "Thread.sleep(Duration) zaman birimini açık hale getirir. 5000'in milisaniye mi yoksa mikrosaniye mi olduğunu artık tahmin etmeye gerek yok. Duration.ofSeconds, ofMillis, ofMinutes vb. ile çalışır." +whyModernWins: +- icon: "📖" + title: "Kendini belgeleyen" + desc: "Duration.ofSeconds(5) belirsizlik taşımaz." +- icon: "🛡️" + title: "Birim güvenli" + desc: "Mikrosaniyeyi yanlışlıkla milisaniye olarak geçirme olmaz." +- icon: "🧩" + title: "Birleştirilebilir" + desc: "Duration matematiği: plus(), multipliedBy() vb." +support: + description: JDK 19'dan itibaren geniş çapta kullanılabilir (Eylül 2022) diff --git a/translations/content/tr/concurrency/virtual-threads.yaml b/translations/content/tr/concurrency/virtual-threads.yaml new file mode 100644 index 0000000..9512464 --- /dev/null +++ b/translations/content/tr/concurrency/virtual-threads.yaml @@ -0,0 +1,18 @@ +--- +title: Sanal iş parçacıkları +oldApproach: Platform İş Parçacıkları +modernApproach: Sanal İş Parçacıkları +summary: "Ağır işletim sistemi iş parçacıkları yerine milyonlarca hafif sanal iş parçacığı oluşturun." +explanation: "Sanal iş parçacıkları, işletim sistemi değil JVM tarafından yönetilen hafif iş parçacıklarıdır. İş parçacığı havuzlarını ayarlamadan milyonlarcasını oluşturabilirsiniz. HTTP çağrıları ve veritabanı sorguları gibi G/Ç'ye bağlı görevler için idealdir." +whyModernWins: +- icon: "⚡" + title: "Hafif" + desc: "Sanal iş parçacıkları KB bellek kullanır, platform iş parçacıkları MB." +- icon: "♾️" + title: "Ölçeklenebilir" + desc: "Milyonlarca iş parçacığı oluşturun — havuz boyutlandırması gerekmez." +- icon: "🧹" + title: "Basit model" + desc: "Asenkron kod gibi ölçeklenen bloklama kodu yazın." +support: + description: JDK 21 LTS'den itibaren geniş çapta kullanılabilir (Eylül 2023) From 78f9ab72777308df4c5607e80d6705f71ab2542f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:30:48 +0000 Subject: [PATCH 18/28] Initial plan From 82b56b5e659df352ad1b03a9df0bd217ac395833 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:32:31 +0000 Subject: [PATCH 19/28] Add missing cards.learnMore key to Italian translations Co-authored-by: brunoborges <129743+brunoborges@users.noreply.github.com> --- translations/strings/it.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/translations/strings/it.yaml b/translations/strings/it.yaml index 0f9e414..7c375c0 100644 --- a/translations/strings/it.yaml +++ b/translations/strings/it.yaml @@ -49,6 +49,7 @@ cards: hoverHint: passa il mouse per vedere il moderno → hoverHintRelated: Passa il mouse per vedere il moderno ➜ touchHint: 👆 tocca o scorri → + learnMore: scopri di più copy: copy: Copia copied: Copiato! From 875ccf09f903199eeeb9f773a331b81afecf664e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:32:35 +0000 Subject: [PATCH 20/28] Add Turkish (tr) translations for datetime and enterprise patterns - 6 datetime files: date-formatting, duration-and-period, hex-format, instant-precision, java-time-basics, math-clamp - 16 enterprise files: ejb-timer-vs-jakarta-scheduler, ejb-vs-cdi, jdbc-resultset-vs-jpa-criteria, jdbc-vs-jooq, jdbc-vs-jpa, jndi-lookup-vs-cdi-injection, jpa-vs-jakarta-data, jsf-managed-bean-vs-cdi-named, manual-transaction-vs-declarative, mdb-vs-reactive-messaging, servlet-vs-jaxrs, singleton-ejb-vs-cdi-application-scoped, soap-vs-jakarta-rest, spring-api-versioning, spring-null-safety-jspecify, spring-xml-config-vs-annotations Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- html-generators/locales.properties | 3 +- .../content/tr/datetime/date-formatting.yaml | 18 ++++ .../tr/datetime/duration-and-period.yaml | 18 ++++ .../content/tr/datetime/hex-format.yaml | 18 ++++ .../tr/datetime/instant-precision.yaml | 18 ++++ .../content/tr/datetime/java-time-basics.yaml | 18 ++++ .../content/tr/datetime/math-clamp.yaml | 18 ++++ .../ejb-timer-vs-jakarta-scheduler.yaml | 18 ++++ .../content/tr/enterprise/ejb-vs-cdi.yaml | 18 ++++ .../jdbc-resultset-vs-jpa-criteria.yaml | 18 ++++ .../content/tr/enterprise/jdbc-vs-jooq.yaml | 18 ++++ .../content/tr/enterprise/jdbc-vs-jpa.yaml | 18 ++++ .../jndi-lookup-vs-cdi-injection.yaml | 18 ++++ .../tr/enterprise/jpa-vs-jakarta-data.yaml | 18 ++++ .../jsf-managed-bean-vs-cdi-named.yaml | 18 ++++ .../manual-transaction-vs-declarative.yaml | 18 ++++ .../enterprise/mdb-vs-reactive-messaging.yaml | 18 ++++ .../tr/enterprise/servlet-vs-jaxrs.yaml | 18 ++++ ...ngleton-ejb-vs-cdi-application-scoped.yaml | 18 ++++ .../tr/enterprise/soap-vs-jakarta-rest.yaml | 18 ++++ .../tr/enterprise/spring-api-versioning.yaml | 18 ++++ .../spring-null-safety-jspecify.yaml | 18 ++++ .../spring-xml-config-vs-annotations.yaml | 18 ++++ translations/strings/tr.yaml | 89 +++++++++++++++++++ 24 files changed, 487 insertions(+), 1 deletion(-) create mode 100644 translations/content/tr/datetime/date-formatting.yaml create mode 100644 translations/content/tr/datetime/duration-and-period.yaml create mode 100644 translations/content/tr/datetime/hex-format.yaml create mode 100644 translations/content/tr/datetime/instant-precision.yaml create mode 100644 translations/content/tr/datetime/java-time-basics.yaml create mode 100644 translations/content/tr/datetime/math-clamp.yaml create mode 100644 translations/content/tr/enterprise/ejb-timer-vs-jakarta-scheduler.yaml create mode 100644 translations/content/tr/enterprise/ejb-vs-cdi.yaml create mode 100644 translations/content/tr/enterprise/jdbc-resultset-vs-jpa-criteria.yaml create mode 100644 translations/content/tr/enterprise/jdbc-vs-jooq.yaml create mode 100644 translations/content/tr/enterprise/jdbc-vs-jpa.yaml create mode 100644 translations/content/tr/enterprise/jndi-lookup-vs-cdi-injection.yaml create mode 100644 translations/content/tr/enterprise/jpa-vs-jakarta-data.yaml create mode 100644 translations/content/tr/enterprise/jsf-managed-bean-vs-cdi-named.yaml create mode 100644 translations/content/tr/enterprise/manual-transaction-vs-declarative.yaml create mode 100644 translations/content/tr/enterprise/mdb-vs-reactive-messaging.yaml create mode 100644 translations/content/tr/enterprise/servlet-vs-jaxrs.yaml create mode 100644 translations/content/tr/enterprise/singleton-ejb-vs-cdi-application-scoped.yaml create mode 100644 translations/content/tr/enterprise/soap-vs-jakarta-rest.yaml create mode 100644 translations/content/tr/enterprise/spring-api-versioning.yaml create mode 100644 translations/content/tr/enterprise/spring-null-safety-jspecify.yaml create mode 100644 translations/content/tr/enterprise/spring-xml-config-vs-annotations.yaml create mode 100644 translations/strings/tr.yaml diff --git a/html-generators/locales.properties b/html-generators/locales.properties index 8d6af5f..40c7bf6 100644 --- a/html-generators/locales.properties +++ b/html-generators/locales.properties @@ -9,4 +9,5 @@ fr=🇫🇷 Français ja=🇯🇵 日本語 ko=🇰🇷 한국어 it=🇮🇹 Italiano -pl=🇵🇱 Polski \ No newline at end of file +pl=🇵🇱 Polski +tr=🇹🇷 Türkçe \ No newline at end of file diff --git a/translations/content/tr/datetime/date-formatting.yaml b/translations/content/tr/datetime/date-formatting.yaml new file mode 100644 index 0000000..04f4dd1 --- /dev/null +++ b/translations/content/tr/datetime/date-formatting.yaml @@ -0,0 +1,18 @@ +--- +title: Tarih biçimlendirme +oldApproach: SimpleDateFormat +modernApproach: DateTimeFormatter +summary: "Tarihleri thread-safe ve değişmez DateTimeFormatter ile biçimlendirin." +explanation: "DateTimeFormatter, SimpleDateFormat'ın aksine değişmez ve thread-safe'dir. Sabit olarak saklanabilir ve paylaşılabilir. Yaygın biçimler için ISO_LOCAL_DATE gibi önceden tanımlanmış biçimleyiciler mevcuttur." +whyModernWins: +- icon: 🛡️ + title: Thread-safe + desc: "Biçimleyicileri senkronizasyon olmadan iş parçacıkları arasında paylaşın." +- icon: 📋 + title: Yerleşik biçimler + desc: "Standart biçimler için ISO_LOCAL_DATE, ISO_INSTANT ve diğerleri." +- icon: 🔒 + title: Değişmez + desc: "Güvenle static final sabit olarak saklayın." +support: + description: JDK 8'den (Mart 2014) itibaren geniş çapta kullanılabilir diff --git a/translations/content/tr/datetime/duration-and-period.yaml b/translations/content/tr/datetime/duration-and-period.yaml new file mode 100644 index 0000000..5865fbd --- /dev/null +++ b/translations/content/tr/datetime/duration-and-period.yaml @@ -0,0 +1,18 @@ +--- +title: Duration ve Period +oldApproach: Milisaniye Matematiği +modernApproach: Duration / Period +summary: "Zaman farklarını tür-güvenli Duration ve Period ile hesaplayın." +explanation: "Duration, saat, dakika ve saniye gibi zaman tabanlı miktarlar içindir. Period ise yıl, ay ve gün gibi tarih tabanlı miktarlar içindir. Basit farklar için ChronoUnit.between() kullanılır. Tümü kenar durumları doğru şekilde ele alır." +whyModernWins: +- icon: 🎯 + title: Tür-güvenli + desc: "Zaman için Duration, tarihler için Period — karışıklık yok." +- icon: 🛡️ + title: Doğru hesaplama + desc: "Yaz saati geçişlerini, artık yılları ve artık saniyeleri doğru ele alır." +- icon: 📖 + title: Okunabilir + desc: "ChronoUnit.DAYS.between() doğal dil gibi okunur." +support: + description: JDK 8'den (Mart 2014) itibaren geniş çapta kullanılabilir diff --git a/translations/content/tr/datetime/hex-format.yaml b/translations/content/tr/datetime/hex-format.yaml new file mode 100644 index 0000000..106ab5e --- /dev/null +++ b/translations/content/tr/datetime/hex-format.yaml @@ -0,0 +1,18 @@ +--- +title: HexFormat +oldApproach: Manuel Hex Dönüşümü +modernApproach: HexFormat +summary: "HexFormat ile hex dizileri ve bayt dizileri arasında dönüşüm yapın." +explanation: "HexFormat, baytlar, int'ler ve diziler için iki yönlü hex kodlama/kod çözme sağlar. Sınırlayıcıları, ön eki, son eki ve büyük/küçük harf kullanımını yapılandırın. Artık manuel biçimlendirme veya ayrıştırma gerekmez." +whyModernWins: +- icon: 📐 + title: İki yönlü + desc: "Tek bir API ile bayt→hex ve hex→bayt dönüşümü yapın." +- icon: 🔧 + title: Yapılandırılabilir + desc: "Sınırlayıcılar, ön ek, son ek, büyük/küçük harf desteği." +- icon: 📦 + title: Dizi desteği + desc: "Tüm bayt dizilerini tek seferde kodlayın/kodunu çözün." +support: + description: JDK 17 LTS'den (Eylül 2021) itibaren geniş çapta kullanılabilir diff --git a/translations/content/tr/datetime/instant-precision.yaml b/translations/content/tr/datetime/instant-precision.yaml new file mode 100644 index 0000000..17c2643 --- /dev/null +++ b/translations/content/tr/datetime/instant-precision.yaml @@ -0,0 +1,18 @@ +--- +title: Nanosaniye hassasiyetli Instant +oldApproach: Milisaniyeler +modernApproach: Nanosaniyeler +summary: "Mikrosaniye veya nanosaniye hassasiyetiyle zaman damgaları alın." +explanation: "Java 9, saat çözünürlüğünü iyileştirdi; böylece Instant.now() çoğu platformda mikrosaniye hassasiyeti (bazılarında nanosaniye) yakalıyor. Eski currentTimeMillis() yalnızca milisaniye sağlar." +whyModernWins: +- icon: 🎯 + title: Daha yüksek hassasiyet + desc: "Milisaniye yerine mikrosaniye/nanosaniye zaman damgaları." +- icon: 📐 + title: Tür-güvenli + desc: "Instant hassasiyetini taşır — belirsiz long türü yok." +- icon: 🌐 + title: UTC tabanlı + desc: "Instant her zaman UTC'dedir — saat dilimi karışıklığı yok." +support: + description: JDK 9'dan (Eylül 2017) itibaren geniş çapta kullanılabilir diff --git a/translations/content/tr/datetime/java-time-basics.yaml b/translations/content/tr/datetime/java-time-basics.yaml new file mode 100644 index 0000000..22b435d --- /dev/null +++ b/translations/content/tr/datetime/java-time-basics.yaml @@ -0,0 +1,18 @@ +--- +title: java.time API temelleri +oldApproach: Date + Calendar +modernApproach: java.time.* +summary: "Date ve Calendar yerine değişmez ve açık tarih/saat türlerini kullanın." +explanation: "java.time; LocalDate, LocalTime, LocalDateTime, Instant, ZonedDateTime sağlar — hepsi değişmez ve thread-safe'dir. Aylar 1'den başlar. Artık Calendar.JANUARY = 0 karışıklığı yok." +whyModernWins: +- icon: 🔒 + title: Değişmez + desc: "Tarih/saat değerleri yanlışlıkla değiştirilemez." +- icon: 📖 + title: Açık API + desc: "0 değil Month.JANUARY; 2 değil DayOfWeek.MONDAY." +- icon: 🛡️ + title: Thread-safe + desc: "Senkronizasyon gerekmez — iş parçacıkları arasında serbestçe paylaşın." +support: + description: JDK 8'den (Mart 2014) itibaren geniş çapta kullanılabilir diff --git a/translations/content/tr/datetime/math-clamp.yaml b/translations/content/tr/datetime/math-clamp.yaml new file mode 100644 index 0000000..db49c49 --- /dev/null +++ b/translations/content/tr/datetime/math-clamp.yaml @@ -0,0 +1,18 @@ +--- +title: Math.clamp() +oldApproach: İç içe min/max +modernApproach: Math.clamp() +summary: "Bir değeri tek ve açık bir çağrıyla sınırlar arasında kısıtlayın." +explanation: "Math.clamp(value, min, max), bir değeri [min, max] aralığıyla kısıtlar. İç içe Math.min/Math.max'tan daha açık ve int, long, float ve double için kullanılabilir." +whyModernWins: +- icon: 📖 + title: Kendini belgeleyen + desc: "clamp(value, min, max) belirsizlik içermez." +- icon: 🛡️ + title: Daha az hata eğilimli + desc: "Artık min/max sırasını yanlışlıkla yer değiştirme riski yok." +- icon: 🎯 + title: Tüm sayısal türler + desc: "int, long, float ve double ile çalışır." +support: + description: JDK 21 LTS'den (Eylül 2023) itibaren geniş çapta kullanılabilir diff --git a/translations/content/tr/enterprise/ejb-timer-vs-jakarta-scheduler.yaml b/translations/content/tr/enterprise/ejb-timer-vs-jakarta-scheduler.yaml new file mode 100644 index 0000000..2f76cef --- /dev/null +++ b/translations/content/tr/enterprise/ejb-timer-vs-jakarta-scheduler.yaml @@ -0,0 +1,18 @@ +--- +title: EJB Timer ve Jakarta Scheduler +oldApproach: EJB TimerService +modernApproach: ManagedScheduledExecutorService +summary: "Ağır EJB zamanlayıcıları, daha basit zamanlama için Jakarta Concurrency'nin ManagedScheduledExecutorService'i ile değiştirin." +explanation: "EJB zamanlayıcıları, @Timeout geri çağrısı olan bir @Stateless veya @Singleton bean ve XML ya da ek açıklama tabanlı zamanlama ifadeleri gerektirir. Jakarta Concurrency, tanıdık java.util.concurrent zamanlama API'sini kullanan ManagedScheduledExecutorService sağlar. Sonuç: daha az şablon kod, daha kolay birim testi ve EJB kapsayıcı bağımlılığı yok." +whyModernWins: +- icon: 🪶 + title: Azaltılmış şablon kod + desc: "@Timeout geri çağrısı veya ScheduleExpression yok — standart ScheduledExecutorService API'sini kullanın." +- icon: 🧪 + title: Daha iyi test edilebilirlik + desc: "Düz yöntemler ve executor mock'ları, EJB kapsayıcı olmadan birim testini basit hale getirir." +- icon: ☁️ + title: Buluta uyumlu + desc: "Yönetilen yürütücüler, kapsayıcı yaşam döngüsüyle entegre olur ve hafif çalışma ortamlarında çalışır." +support: + description: Jakarta EE 10 / Concurrency 3.0'dan itibaren kullanılabilir diff --git a/translations/content/tr/enterprise/ejb-vs-cdi.yaml b/translations/content/tr/enterprise/ejb-vs-cdi.yaml new file mode 100644 index 0000000..9d32ebc --- /dev/null +++ b/translations/content/tr/enterprise/ejb-vs-cdi.yaml @@ -0,0 +1,18 @@ +--- +title: EJB ile CDI Karşılaştırması +oldApproach: EJB +modernApproach: CDI Bean +summary: "Bağımlılık enjeksiyonu ve işlemler için ağır EJB'leri hafif CDI bean'leri ile değiştirin." +explanation: "CDI (Contexts and Dependency Injection), EJB'lerle aynı bağımlılık enjeksiyonu ve işlem yönetimini sağlar; ancak kapsayıcıya özel arayüzler veya üst sınıflar olmadan düz Java sınıfları olarak. @ApplicationScoped ve @RequestScoped gibi kapsamlar yaşam döngüsünü kontrol eder; @Transactional ise zorunlu EJB işlem semantiğinin yerini alır." +whyModernWins: +- icon: 🪶 + title: Hafif + desc: "CDI bean'leri, EJB'ye özel arayüzler veya tanımlayıcılar olmadan düz Java sınıflarıdır." +- icon: 💉 + title: Birleşik enjeksiyon + desc: "@Inject; tüm yönetilen bean'ler, JAX-RS kaynakları ve Jakarta EE bileşenlerinde çalışır." +- icon: 🧪 + title: Kolay birim testi + desc: "EJB proxy ek yükü olmayan düz sınıflar, örneklendirmek ve mock'lamak için çok daha basittir." +support: + description: Jakarta EE 8 / Java 11'den itibaren geniş çapta kullanılabilir diff --git a/translations/content/tr/enterprise/jdbc-resultset-vs-jpa-criteria.yaml b/translations/content/tr/enterprise/jdbc-resultset-vs-jpa-criteria.yaml new file mode 100644 index 0000000..d9c303f --- /dev/null +++ b/translations/content/tr/enterprise/jdbc-resultset-vs-jpa-criteria.yaml @@ -0,0 +1,18 @@ +--- +title: JDBC ResultSet Eşleme ile JPA Criteria API Karşılaştırması +oldApproach: JDBC ResultSet +modernApproach: JPA Criteria API +summary: "Dinamik sorgular için manuel JDBC ResultSet eşlemesini JPA'nın tür-güvenli Criteria API'siyle değiştirin." +explanation: "Ham JDBC, SQL dizilerinin oluşturulmasını, parametrelerin dizine göre ayarlanmasını ve her ResultSet sütununun manuel olarak eşlenmesini gerektirir — bu süreç hata eğilimlidir ve sütunlar değiştiğinde sessizce bozulur. JPA Criteria API, tür-güvenli bir oluşturucu deseni kullanarak sorguları programatik olarak oluşturur. Sütun adları entity modeline göre doğrulanır, sonuç eşlemesi otomatik yapılır ve karmaşık dinamik sorgular dize birleştirme olmadan temiz biçimde oluşturulur." +whyModernWins: +- icon: 🔒 + title: Tür-güvenli sorgular + desc: "Criteria oluşturucusu, alan adı ve tür uyumsuzluklarını derleme zamanında yakalar." +- icon: 🗺️ + title: Otomatik eşleme + desc: "JPA, sonuç satırlarını entity nesnelerine eşler — sütun bazında manuel çıkarma yok." +- icon: 🧩 + title: Birleştirilebilir koşullar + desc: "Dinamik where koşulları, and(), or() ve yeniden kullanılabilir Predicate nesneleriyle temiz biçimde oluşturulur." +support: + description: Jakarta EE 8 / Java 11'den itibaren geniş çapta kullanılabilir diff --git a/translations/content/tr/enterprise/jdbc-vs-jooq.yaml b/translations/content/tr/enterprise/jdbc-vs-jooq.yaml new file mode 100644 index 0000000..3d25790 --- /dev/null +++ b/translations/content/tr/enterprise/jdbc-vs-jooq.yaml @@ -0,0 +1,18 @@ +--- +title: JDBC ile jOOQ Karşılaştırması +oldApproach: Ham JDBC +modernApproach: jOOQ SQL DSL +summary: "Ham JDBC dize tabanlı SQL'i jOOQ'nun tür-güvenli, akıcı SQL DSL'i ile değiştirin." +explanation: "jOOQ (Java Object Oriented Querying), veritabanı şemanızdan Java kodu üretir; tablo ve sütun adlarını tür-güvenli Java sabitlerına dönüştürür. Akıcı DSL, SQL söz dizimini yansıtır; böylece sorgular okunabilir ve birleştirilebilir olur. Tüm parametreler otomatik olarak bağlanır ve SQL enjeksiyonu riski ortadan kalkar. JPA/JPQL'den farklı olarak jOOQ, SQL'i tam anlamıyla benimser — pencere fonksiyonları, CTE'ler, RETURNING cümleleri ve satıcıya özgü uzantılar birinci sınıf desteklenir." +whyModernWins: +- icon: 🔒 + title: Tür-güvenli sütunlar + desc: "Sütun adları üretilmiş Java sabitleridir — yazım hataları ve tür uyumsuzlukları çalışma zamanı hataları yerine derleyici hatalarına dönüşür." +- icon: 📖 + title: SQL akıcılığı + desc: "jOOQ DSL, SQL söz dizimini yakından yansıtır; karmaşık JOIN'ler, alt sorgular ve CTE'ler okunabilir kalır." +- icon: 🛡️ + title: Tasarım gereği enjeksiyonsuz + desc: "Parametreler her zaman güvenli şekilde bağlanır — dize birleştirme olmadığından SQL enjeksiyonu riski yoktur." +support: + description: "jOOQ açık kaynak sürümü tüm büyük açık kaynak veritabanlarını destekler; eski ticari veritabanlar ücretli lisans gerektirir" diff --git a/translations/content/tr/enterprise/jdbc-vs-jpa.yaml b/translations/content/tr/enterprise/jdbc-vs-jpa.yaml new file mode 100644 index 0000000..1836978 --- /dev/null +++ b/translations/content/tr/enterprise/jdbc-vs-jpa.yaml @@ -0,0 +1,18 @@ +--- +title: JDBC ile JPA Karşılaştırması +oldApproach: JDBC +modernApproach: JPA EntityManager +summary: "Ayrıntılı JDBC şablon kodunu JPA'nın nesne-ilişkisel eşleme ve EntityManager'ı ile değiştirin." +explanation: "JPA (Jakarta Persistence API), Java nesnelerini veritabanı satırlarına eşler; manuel ResultSet işleme ve SQL dize birleştirmeyi ortadan kaldırır. EntityManager, find(), persist() ve JPQL sorguları sağlar; böylece ham SQL yerine etki alanı nesneleriyle çalışırsınız; kapsayıcı ise bağlantı havuzlama ve işlemleri yönetir." +whyModernWins: +- icon: 🗺️ + title: Nesne eşleme + desc: "Entity'ler düz açıklamalı sınıflardır — manuel ResultSet'ten nesneye çeviri yok." +- icon: 🔒 + title: Tür-güvenli sorgular + desc: "JPQL, ham tablo ve sütun dizeleri yerine entity türleri ve alanlar üzerinde çalışır." +- icon: ⚡ + title: Yerleşik önbellekleme + desc: "Birinci ve ikinci düzey önbellekler, veritabanı gidiş-dönüşlerini otomatik olarak azaltır." +support: + description: Jakarta EE 8 / Java 11'den itibaren geniş çapta kullanılabilir diff --git a/translations/content/tr/enterprise/jndi-lookup-vs-cdi-injection.yaml b/translations/content/tr/enterprise/jndi-lookup-vs-cdi-injection.yaml new file mode 100644 index 0000000..4120782 --- /dev/null +++ b/translations/content/tr/enterprise/jndi-lookup-vs-cdi-injection.yaml @@ -0,0 +1,18 @@ +--- +title: JNDI Arama ile CDI Enjeksiyonu Karşılaştırması +oldApproach: JNDI Arama +modernApproach: CDI @Inject +summary: "Kırılgan JNDI dize aramalarını, kapsayıcı tarafından yönetilen kaynaklar için tür-güvenli CDI enjeksiyonuyla değiştirin." +explanation: "Geleneksel JNDI deseni, dize tabanlı kaynak adları kullanmayı, NamingException'ı işlemeyi ve bir InitialContext yönetmeyi zorlar. @Inject (veya kapsayıcı kaynakları için @Resource) ile CDI enjeksiyonu, kapsayıcının bağımlılıkları otomatik olarak bağlamasını sağlar. Yazım hataları derleme zamanı hatalarına dönüşür ve sınıflar, bağımlılıklar doğrudan enjekte edilebildiğinden test edilmesi daha kolaydır." +whyModernWins: +- icon: 🔒 + title: Tür-güvenli bağlama + desc: "Enjeksiyon hataları, dize aramaları yerine dağıtım zamanında yakalanır." +- icon: 🗑️ + title: Şablon kod yok + desc: "InitialContext oluşturma, JNDI ad dizeleri ve NamingException işlemeyi ortadan kaldırır." +- icon: 🧪 + title: Test edilebilir + desc: "Bağımlılıklar enjekte edilmiş alanlardır; birim testlerinde mock'larla kolayca değiştirilebilir." +support: + description: Jakarta EE 8 / Java 11'den itibaren geniş çapta kullanılabilir diff --git a/translations/content/tr/enterprise/jpa-vs-jakarta-data.yaml b/translations/content/tr/enterprise/jpa-vs-jakarta-data.yaml new file mode 100644 index 0000000..0767b15 --- /dev/null +++ b/translations/content/tr/enterprise/jpa-vs-jakarta-data.yaml @@ -0,0 +1,18 @@ +--- +title: JPA ile Jakarta Data Karşılaştırması +oldApproach: JPA EntityManager +modernApproach: Jakarta Data Repository +summary: "Bir repository arayüzü tanımlayın ve Jakarta Data'nın DAO uygulamasını otomatik olarak oluşturmasına izin verin." +explanation: "Jakarta Data (Jakarta EE 11), veri erişimini saf bir arayüz bildirimine dönüştürür. Bir arayüzü @Repository ile açıklarsınız ve CrudRepository gibi yerleşik bir repository türünü genişletirsiniz. Çalışma zamanı, findByName gibi yöntem adlarından türetilmiş sorgular dahil uygulamayı üretir — dolayısıyla EntityManager şablon kodu, JPQL dizeleri ve elle yazılmış save/find yöntemleri yoktur." +whyModernWins: +- icon: 🪄 + title: Sıfır şablon kod + desc: "Arayüzü tanımlayın; kapsayıcı dağıtım zamanında tam DAO uygulamasını üretir." +- icon: 🔍 + title: Türetilmiş sorgular + desc: "findByNameAndStatus gibi yöntem adları otomatik olarak ayrıştırılır — JPQL veya SQL gerekmez." +- icon: 🔌 + title: Taşınabilir + desc: "Jakarta EE 11 uyumlu herhangi bir çalışma ortamı, satıcı bağımlılığı olmadan repository uygulamasını sağlar." +support: + description: Jakarta EE 11 / Java 21'den itibaren kullanılabilir (2024) diff --git a/translations/content/tr/enterprise/jsf-managed-bean-vs-cdi-named.yaml b/translations/content/tr/enterprise/jsf-managed-bean-vs-cdi-named.yaml new file mode 100644 index 0000000..17d5e9b --- /dev/null +++ b/translations/content/tr/enterprise/jsf-managed-bean-vs-cdi-named.yaml @@ -0,0 +1,18 @@ +--- +title: JSF Managed Bean ile CDI Named Bean Karşılaştırması +oldApproach: "@ManagedBean" +modernApproach: "@Named + CDI" +summary: "Birleşik bir bağımlılık enjeksiyonu modeli için kullanımdan kaldırılmış JSF @ManagedBean'i CDI @Named ile değiştirin." +explanation: "JSF'in @ManagedBean ve @ManagedProperty'si, Jakarta Faces 2.3'te kullanımdan kaldırıldı ve Jakarta EE 10'da kaldırıldı. CDI tabanlı değişiklik, bean'i EL ifadelerine açmak için @Named ve bağımlılık bağlama için @Inject kullanır. Bu, bean modelini birleştirir: JSF sayfaları, JAX-RS kaynakları ve EJB'ler aynı CDI kapsayıcısını paylaşır." +whyModernWins: +- icon: 🔗 + title: Birleşik model + desc: "Tek bir CDI kapsayıcısı tüm bean'leri yönetir — JSF, REST ve hizmet katmanları aynı enjeksiyonu paylaşır." +- icon: 🗑️ + title: Daha az şablon kod + desc: "@Inject, @ManagedProperty ve gerekli setter yönteminin yerini alır." +- icon: 🔮 + title: Geleceğe hazır + desc: "@ManagedBean, Jakarta EE 10'da kaldırılmıştır; @Named desteklenen yerini alandır." +support: + description: "CDI @Named Java EE 6'dan itibaren kullanılabilir; @ManagedBean Jakarta EE 10'da kaldırılmıştır" diff --git a/translations/content/tr/enterprise/manual-transaction-vs-declarative.yaml b/translations/content/tr/enterprise/manual-transaction-vs-declarative.yaml new file mode 100644 index 0000000..309eeba --- /dev/null +++ b/translations/content/tr/enterprise/manual-transaction-vs-declarative.yaml @@ -0,0 +1,18 @@ +--- +title: Manuel JPA İşlemi ile Bildirimsel @Transactional Karşılaştırması +oldApproach: Manuel İşlem +modernApproach: "@Transactional" +summary: "Ayrıntılı begin/commit/rollback bloklarını tek bir @Transactional açıklamasıyla değiştirin." +explanation: "Manuel işlem yönetimi, try-catch bloklarına sarılmış açık begin(), commit() ve rollback() çağrıları gerektirir — her hizmet yöntemi bu şablon kodu tekrar eder. @Transactional açıklaması, yaşam döngüsü yönetimini kapsayıcıya devreder: yöntemden önce bir işlem başlatır, başarıda commit eder ve RuntimeException durumunda otomatik olarak geri alır." +whyModernWins: +- icon: 🗑️ + title: Şablon kod yok + desc: "Tek bir açıklama, tekrarlayan begin/commit/rollback try-catch bloklarının yerini alır." +- icon: 🛡️ + title: Daha güvenli geri alma + desc: "Kapsayıcı, denetlenmemiş istisnalarda geri almayı garanti eder — catch bloğunu unutma riski yok." +- icon: 📐 + title: Bildirimsel kontrol + desc: "Yayılım, yalıtım ve geri alma kuralları açıklama öznitelikleri olarak ifade edilir." +support: + description: Jakarta EE 8 / Java 11'den itibaren geniş çapta kullanılabilir diff --git a/translations/content/tr/enterprise/mdb-vs-reactive-messaging.yaml b/translations/content/tr/enterprise/mdb-vs-reactive-messaging.yaml new file mode 100644 index 0000000..019494c --- /dev/null +++ b/translations/content/tr/enterprise/mdb-vs-reactive-messaging.yaml @@ -0,0 +1,18 @@ +--- +title: Message-Driven Bean ile Reactive Messaging Karşılaştırması +oldApproach: Message-Driven Bean +modernApproach: Reactive Messaging +summary: "Daha basit olay işleme için JMS Message-Driven Bean'leri MicroProfile Reactive Messaging ile değiştirin." +explanation: "Message-Driven Bean'ler, MessageListener'ı uygulamayı, etkinleştirme özelliklerini yapılandırmayı ve JMS iletilerini manuel olarak seri dışı bırakmayı gerektirir. MicroProfile Reactive Messaging, doğrudan yazılı nesneler alan bir yöntem üzerinde basit bir @Incoming açıklaması kullanır. Kanal yapılandırması dışarı çıkarılır; bu da kodu aracı-agnostik ve test edilmesi çok daha kolay hale getirir." +whyModernWins: +- icon: 🪶 + title: Minimal kod + desc: "Tek bir @Incoming yöntemi, MDB sınıfının, MessageListener arayüzünün ve etkinleştirme yapılandırmasının yerini alır." +- icon: 🔌 + title: Aracı-agnostik + desc: "Uygulama kodunu değiştirmeden yapılandırma yoluyla Kafka, AMQP veya JMS bağlayıcılarını değiştirin." +- icon: ☁️ + title: Buluta uyumlu + desc: "Reaktif akışlar geri baskısı ve hafif çalışma ortamı, konteynerleştirilmiş dağıtımlar için idealdir." +support: + description: MicroProfile 4.0 / SmallRye Reactive Messaging'den itibaren kullanılabilir diff --git a/translations/content/tr/enterprise/servlet-vs-jaxrs.yaml b/translations/content/tr/enterprise/servlet-vs-jaxrs.yaml new file mode 100644 index 0000000..c0ff7b7 --- /dev/null +++ b/translations/content/tr/enterprise/servlet-vs-jaxrs.yaml @@ -0,0 +1,18 @@ +--- +title: Servlet ile JAX-RS Karşılaştırması +oldApproach: HttpServlet +modernApproach: JAX-RS Resource +summary: "Ayrıntılı HttpServlet şablon kodunu bildirimsel JAX-RS kaynak sınıflarıyla değiştirin." +explanation: "JAX-RS (Jakarta RESTful Web Services), @GET, @Path ve @Produces gibi basit açıklamalar kullanarak REST uç noktaları açığa çıkarmanızı sağlar. Artık istek parametrelerini manuel olarak ayrıştırmaya veya yanıtta içerik türlerini ayarlamaya gerek yok — çalışma zamanı, sıralama ve yönlendirmeyi otomatik olarak yönetir." +whyModernWins: +- icon: 📐 + title: Bildirimsel yönlendirme + desc: "Açıklamalar, zorunlu if/else dağıtımı yerine HTTP yöntemini, yolu ve içerik türünü tanımlar." +- icon: 🔄 + title: Otomatik sıralama + desc: "POJO'ları doğrudan döndürün; çalışma zamanı bunları @Produces'a göre JSON veya XML'e serileştirir." +- icon: 🧪 + title: Daha kolay test + desc: "Kaynak sınıfları düz Java nesneleridir; servlet kapsayıcısı olmadan test edilebilir." +support: + description: Jakarta EE 8 / Java 11'den itibaren geniş çapta kullanılabilir diff --git a/translations/content/tr/enterprise/singleton-ejb-vs-cdi-application-scoped.yaml b/translations/content/tr/enterprise/singleton-ejb-vs-cdi-application-scoped.yaml new file mode 100644 index 0000000..3eeaa39 --- /dev/null +++ b/translations/content/tr/enterprise/singleton-ejb-vs-cdi-application-scoped.yaml @@ -0,0 +1,18 @@ +--- +title: Singleton EJB ile CDI @ApplicationScoped Karşılaştırması +oldApproach: "@Singleton EJB" +modernApproach: "@ApplicationScoped CDI" +summary: "Singleton EJB'leri daha basit paylaşılan durum yönetimi için CDI @ApplicationScoped bean'lerle değiştirin." +explanation: "Singleton EJB'ler, eşzamanlılık yönetimini (@Lock, @ConcurrencyManagement) ve istekli başlatmayı (@Startup) EJB kapsayıcısına dahil eder. Bir CDI @ApplicationScoped bean, çok daha az törenle aynı tek örnek yaşam döngüsünü elde eder. Eşzamanlılık kontrolü gerektiğinde, standart java.util.concurrent yardımcı programları EJB kilit açıklamalarından daha ince taneli kontrol sağlar." +whyModernWins: +- icon: 🪶 + title: Daha az açıklama gürültüsü + desc: "@ConcurrencyManagement, @Lock veya @Startup yok — yalnızca tek bir @ApplicationScoped açıklaması." +- icon: 🔧 + title: Esnek eşzamanlılık + desc: "Tam olarak ihtiyacınız olan iş parçacığı güvenliği için java.util.concurrent kilitleri veya volatile kullanın." +- icon: 🧪 + title: Kolay test + desc: "Düz CDI bean'leri, EJB kapsayıcısı olmadan testlerde doğrudan örneklendirilebilir." +support: + description: Jakarta EE 8 / Java 11'den itibaren geniş çapta kullanılabilir diff --git a/translations/content/tr/enterprise/soap-vs-jakarta-rest.yaml b/translations/content/tr/enterprise/soap-vs-jakarta-rest.yaml new file mode 100644 index 0000000..1b0fa81 --- /dev/null +++ b/translations/content/tr/enterprise/soap-vs-jakarta-rest.yaml @@ -0,0 +1,18 @@ +--- +title: SOAP Web Servisleri ile Jakarta REST Karşılaştırması +oldApproach: JAX-WS / SOAP +modernApproach: Jakarta REST / JSON +summary: "Ağır SOAP/WSDL uç noktalarını JSON döndüren temiz Jakarta REST kaynaklarıyla değiştirin." +explanation: "SOAP tabanlı web servisleri, önemli ek yük katan WSDL sözleşmeleri, XML sıralama ve JAX-WS açıklamalarına dayanır. Jakarta REST (eski adıyla JAX-RS), RESTful JSON API'lerini açığa çıkarmak için @GET, @Path ve @Produces gibi sezgisel açıklamalar kullanır. Programlama modeli daha basit, yükler daha küçük ve yaklaşım modern mikro servislerin iletişim biçimiyle örtüşüyor." +whyModernWins: +- icon: 🪶 + title: Daha hafif yükler + desc: "JSON, SOAP XML zarflarına kıyasla daha kompakttır; bant genişliği ve ayrıştırma ek yükünü azaltır." +- icon: 📐 + title: Basit açıklamalar + desc: "@GET, @Path ve @Produces; WSDL, @WebService ve @WebMethod töreninin yerini alır." +- icon: 🔌 + title: Mikro servise hazır + desc: "REST/JSON, buluta özgü mimarilerde servisler arası iletişimin standardıdır." +support: + description: Jakarta EE 8 / Java 11'den itibaren geniş çapta kullanılabilir diff --git a/translations/content/tr/enterprise/spring-api-versioning.yaml b/translations/content/tr/enterprise/spring-api-versioning.yaml new file mode 100644 index 0000000..7c3c30f --- /dev/null +++ b/translations/content/tr/enterprise/spring-api-versioning.yaml @@ -0,0 +1,18 @@ +--- +title: Spring Framework 7 API Sürümlendirme +oldApproach: Manuel URL Yolu Sürümlendirme +modernApproach: Yerel API Sürümlendirme +summary: "Yinelenen sürüm önekli controller'ları Spring Framework 7'nin yerel API sürümlendirme desteğiyle değiştirin." +explanation: "Spring Framework 7 öncesinde, API sürümlendirme her sürüm için ayrı controller sınıfları gerektiriyordu (örn. /api/v1/products, /api/v2/products); bu da istek eşlemelerini kopyalıyor ve sürüm mantığını birçok dosyaya yayıyordu. Spring Framework 7, @RequestMapping ve ilgili açıklamalardaki yeni version özniteliği ile WebMvcConfigurer'daki configureApiVersioning kancası aracılığıyla yerel sürümlendirmeyi tanıtıyor. Sürüm, bir istek başlığından, URL yolu segmentinden veya sorgu parametresinden çözümlenebilir — hepsi tek bir yerde kontrol edilir." +whyModernWins: +- icon: 🗂️ + title: Controller yinelemesi yok + desc: "Tüm sürümler tek bir controller sınıfında yaşar; yalnızca bireysel işleyici yöntemleri bir version özniteliği taşır." +- icon: ⚙️ + title: Merkezi sürüm stratejisi + desc: "Tek bir configureApiVersioning çağrısıyla başlıktan URL'ye veya sorgu parametresi sürümlendirmesine geçin." +- icon: 📈 + title: Kademeli gelişim + desc: "İlgisiz uç noktalara dokunmadan veya yeni controller dosyaları oluşturmadan tek bir yönteme yeni bir sürüm ekleyin." +support: + description: Spring Framework 7.0'dan itibaren kullanılabilir (Java 17+ gerektirir) diff --git a/translations/content/tr/enterprise/spring-null-safety-jspecify.yaml b/translations/content/tr/enterprise/spring-null-safety-jspecify.yaml new file mode 100644 index 0000000..2c73e6e --- /dev/null +++ b/translations/content/tr/enterprise/spring-null-safety-jspecify.yaml @@ -0,0 +1,18 @@ +--- +title: JSpecify ile Spring Null Safety +oldApproach: Spring @NonNull/@Nullable +modernApproach: JSpecify @NullMarked +summary: "Spring 7, JSpecify açıklamalarını benimseyerek null olmayan değeri varsayılan yapar ve açıklama gürültüsünü azaltır." +explanation: "Spring 5 ve 6, org.springframework.lang paketinde kendi null güvenlik açıklamalarını tanıttı. Yararlı olmakla birlikte bunlar çerçeveye özgüydü ve her null olmayan öğeyi açıkça açıklamayı gerektiriyordu. Spring 7, null güvenliği için çapraz ekosistem standardı olan JSpecify'a geçiş yapıyor. Sınıf veya paket düzeyindeki @NullMarked açıklaması, açıklanmamış tüm türlerin varsayılan olarak null olmayan olduğunu belirtir. Yalnızca gerçekten null olabilecek türlerin @Nullable açıklamasına ihtiyacı vardır; bu da ayrıntıyı önemli ölçüde azaltır. JSpecify açıklamaları NullAway, Error Prone ve IntelliJ IDEA gibi büyük statik analiz araçları tarafından tanınır ve Spring'e özgü açıklamaların sağladığından daha zengin araç desteği sunar." +whyModernWins: +- icon: ✂️ + title: Varsayılan olarak null olmayan + desc: "@NullMarked, açıklanmamış tüm türleri null olmayan yapar; yalnızca nullable istisnalar açıklama gerektirir." +- icon: 🌐 + title: Ekosistem standardı + desc: "JSpecify açıklamaları, NullAway, Error Prone ve IDE'ler tarafından tanınan çapraz çerçeve standardıdır." +- icon: 🔍 + title: Daha zengin araç desteği + desc: "Modern statik analizörler JSpecify'ın null modelini anlar ve ihlalleri derleme zamanında bildirir." +support: + description: Spring Framework 7.0'dan itibaren kullanılabilir (Java 17+ gerektirir) diff --git a/translations/content/tr/enterprise/spring-xml-config-vs-annotations.yaml b/translations/content/tr/enterprise/spring-xml-config-vs-annotations.yaml new file mode 100644 index 0000000..db57a46 --- /dev/null +++ b/translations/content/tr/enterprise/spring-xml-config-vs-annotations.yaml @@ -0,0 +1,18 @@ +--- +title: Spring XML Bean Yapılandırması ile Açıklama Tabanlı Karşılaştırması +oldApproach: XML Bean Tanımları +modernApproach: Açıklama Tabanlı Bean'ler +summary: "Ayrıntılı Spring XML bean tanımlarını Spring Boot'ta özlü açıklama tabanlı yapılandırmayla değiştirin." +explanation: "Geleneksel Spring uygulamaları, her sınıfı ve bağımlılıklarını ayrıntılı öğeleri olarak bildiren XML yapılandırma dosyaları aracılığıyla bean'leri bağlardı. Spring 2.5'ten itibaren açıklama desteği mevcut olsa da Spring Boot otomatik yapılandırmayı tanıtana kadar XML baskın yaklaşım olmaya devam etti. Spring Boot, classpath taraması yoluyla @Component, @Service, @Repository ve @Controller ile açıklanmış bean'leri algılar, kurucu enjeksiyon yoluyla bağımlılıkları otomatik karşılar ve classpath'ten DataSource gibi altyapıyı yapılandırır — tüm XML bağlama dosyalarını ortadan kaldırır." +whyModernWins: +- icon: 🚫 + title: XML yok + desc: "@SpringBootApplication, bileşen taramayı ve otomatik yapılandırmayı tetikler; tüm XML bağlama dosyalarını ortadan kaldırır." +- icon: 💉 + title: Kurucu enjeksiyon + desc: "Spring, bağımlılıkları otomatik olarak kurucular aracılığıyla enjekte eder; bean'leri test etmeyi ve anlamayı kolaylaştırır." +- icon: ⚡ + title: Otomatik yapılandırma + desc: "Spring Boot, DataSource, JPA ve diğer altyapıyı classpath'ten sıfır şablon kodla yapılandırır." +support: + description: "Spring Boot 1.0'dan (Nisan 2014) itibaren geniş çapta kullanılabilir; Spring Boot 3 Java 17+ gerektirir" diff --git a/translations/strings/tr.yaml b/translations/strings/tr.yaml new file mode 100644 index 0000000..a04e498 --- /dev/null +++ b/translations/strings/tr.yaml @@ -0,0 +1,89 @@ +site: + title: java.evolved + tagline: Java gelişti. Kodun da gelişebilir. + tagline_line1: Java gelişti. + tagline_line2: Kodun da gelişebilir. + description: Modern Java kod parçacıklarından oluşan bir koleksiyon. Her eski Java deseni, temiz ve modern karşılığının yanında — yan yana. + heroSnippetCount: ✦ {{snippetCount}} modern desen · Java 8 → Java 25 + heroOld: Eski + heroModern: Modern + allComparisons: Tüm karşılaştırmalar + snippetsBadge: '{{snippetCount}} parçacık' +nav: + allPatterns: ← Tüm desenler + toggleTheme: Temayı değiştir + viewOnGitHub: GitHub'da görüntüle + selectLanguage: Dil seç +breadcrumb: + home: Ana Sayfa +sections: + codeComparison: Kod Karşılaştırması + whyModernWins: Modern yöntem neden daha iyi + oldApproach: Eski Yaklaşım + modernApproach: Modern Yaklaşım + sinceJdk: JDK'dan itibaren + difficulty: Zorluk + jdkSupport: JDK Desteği + howItWorks: Nasıl çalışır + relatedDocs: İlgili Belgeler + relatedPatterns: İlgili desenler +filters: + show: 'Göster:' + all: Tümü +difficulty: + beginner: Başlangıç + intermediate: Orta + advanced: İleri +search: + placeholder: Parçacık ara… + noResults: Sonuç bulunamadı. + esc: ESC + searchTrigger: Ara… + navigate: gezin + open: aç + close: kapat +cards: + old: Eski + modern: Modern + hoverHint: modernini görmek için üzerine gel → + hoverHintRelated: Modernini görmek için üzerine gel ➜ + touchHint: 👆 dokun veya kaydır → + learnMore: daha fazla bilgi +copy: + copy: Kopyala + copied: Kopyalandı! +share: + label: Paylaş +view: + expandAll: Tümünü Genişlet + collapseAll: Tümünü Daralt +stats: + modernPatterns: Modern Desenler + jdkVersions: Kapsanan JDK Sürümleri + categories: Kategoriler + linesOfPython: Gereken Python Satırı +footer: + tagline: Java gelişti. Kodun da gelişebilir. + madeWith: ❤️ ile yapıldı + and: ve + inspiredBy: İlham kaynağı + viewOnGitHub: GitHub'da görüntüle +copilot: + headline: Java kod tabanınızı GitHub Copilot ile modernleştirin. + description: Copilot'un eski desenleri modern Java'ya otomatik olarak geçirmenize yardımcı olmasına izin verin. + appModernization: Uygulama Modernizasyonu → + javaGuide: Java Kılavuzu → +support: + available: Mevcut + preview: Önizleme + experimental: Deneysel +contribute: + button: Katkıda Bulun + codeIssue: Kod sorunu bildir + translationIssue: Çeviri sorunu bildir + suggestPattern: Yeni desen öner + seeIssue: "Bu kodda bir sorun mu gördünüz?" + reportIt: "Bize bildirin." +untranslated: + notice: Bu sayfa henüz {{localeName}} diline çevrilmemiştir. + viewInEnglish: İngilizce olarak görüntüle From d60776663a5147d1f595de953c8c123efed3ceae Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:36:35 +0000 Subject: [PATCH 21/28] Add Turkish (tr) translations for errors, io, and security categories Translate 22 content YAML files to Turkish: - errors: helpful-npe, multi-catch, null-in-switch, optional-chaining, optional-orelsethrow, record-based-errors, require-nonnull-else - io: deserialization-filters, file-memory-mapping, files-mismatch, http-client, inputstream-transferto, io-class-console-io, path-of, reading-files, try-with-resources-effectively-final, writing-files - security: key-derivation-functions, pem-encoding, random-generator, strong-random, tls-default Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../content/tr/errors/helpful-npe.yaml | 18 ++++++++++++++++++ .../content/tr/errors/multi-catch.yaml | 18 ++++++++++++++++++ .../content/tr/errors/null-in-switch.yaml | 18 ++++++++++++++++++ .../content/tr/errors/optional-chaining.yaml | 18 ++++++++++++++++++ .../tr/errors/optional-orelsethrow.yaml | 18 ++++++++++++++++++ .../content/tr/errors/record-based-errors.yaml | 18 ++++++++++++++++++ .../tr/errors/require-nonnull-else.yaml | 18 ++++++++++++++++++ .../content/tr/io/deserialization-filters.yaml | 18 ++++++++++++++++++ .../content/tr/io/file-memory-mapping.yaml | 18 ++++++++++++++++++ translations/content/tr/io/files-mismatch.yaml | 18 ++++++++++++++++++ translations/content/tr/io/http-client.yaml | 18 ++++++++++++++++++ .../content/tr/io/inputstream-transferto.yaml | 18 ++++++++++++++++++ .../content/tr/io/io-class-console-io.yaml | 18 ++++++++++++++++++ translations/content/tr/io/path-of.yaml | 18 ++++++++++++++++++ translations/content/tr/io/reading-files.yaml | 18 ++++++++++++++++++ .../try-with-resources-effectively-final.yaml | 18 ++++++++++++++++++ translations/content/tr/io/writing-files.yaml | 18 ++++++++++++++++++ .../tr/security/key-derivation-functions.yaml | 18 ++++++++++++++++++ .../content/tr/security/pem-encoding.yaml | 18 ++++++++++++++++++ .../content/tr/security/random-generator.yaml | 18 ++++++++++++++++++ .../content/tr/security/strong-random.yaml | 18 ++++++++++++++++++ .../content/tr/security/tls-default.yaml | 18 ++++++++++++++++++ 22 files changed, 396 insertions(+) create mode 100644 translations/content/tr/errors/helpful-npe.yaml create mode 100644 translations/content/tr/errors/multi-catch.yaml create mode 100644 translations/content/tr/errors/null-in-switch.yaml create mode 100644 translations/content/tr/errors/optional-chaining.yaml create mode 100644 translations/content/tr/errors/optional-orelsethrow.yaml create mode 100644 translations/content/tr/errors/record-based-errors.yaml create mode 100644 translations/content/tr/errors/require-nonnull-else.yaml create mode 100644 translations/content/tr/io/deserialization-filters.yaml create mode 100644 translations/content/tr/io/file-memory-mapping.yaml create mode 100644 translations/content/tr/io/files-mismatch.yaml create mode 100644 translations/content/tr/io/http-client.yaml create mode 100644 translations/content/tr/io/inputstream-transferto.yaml create mode 100644 translations/content/tr/io/io-class-console-io.yaml create mode 100644 translations/content/tr/io/path-of.yaml create mode 100644 translations/content/tr/io/reading-files.yaml create mode 100644 translations/content/tr/io/try-with-resources-effectively-final.yaml create mode 100644 translations/content/tr/io/writing-files.yaml create mode 100644 translations/content/tr/security/key-derivation-functions.yaml create mode 100644 translations/content/tr/security/pem-encoding.yaml create mode 100644 translations/content/tr/security/random-generator.yaml create mode 100644 translations/content/tr/security/strong-random.yaml create mode 100644 translations/content/tr/security/tls-default.yaml diff --git a/translations/content/tr/errors/helpful-npe.yaml b/translations/content/tr/errors/helpful-npe.yaml new file mode 100644 index 0000000..fe81c7a --- /dev/null +++ b/translations/content/tr/errors/helpful-npe.yaml @@ -0,0 +1,18 @@ +--- +title: Yardımcı NullPointerException'lar +oldApproach: Belirsiz NPE +modernApproach: Ayrıntılı NPE +summary: "JVM, hangi değişkenin null olduğunu otomatik olarak tam olarak söyler." +explanation: "Yardımcı NPE'ler hangi ifadenin null olduğunu ve hangi işlemin başarısız olduğunu açıklar. Bu özellik Java 14'ten itibaren varsayılan olarak etkindir — herhangi bir kod değişikliğine gerek yoktur, yalnızca JDK'yı yükseltin." +whyModernWins: +- icon: "🔍" + title: "Tam değişken" + desc: "Mesaj, zincirdeki null değişkeni adlandırır." +- icon: "⚡" + title: "Daha hızlı hata ayıklama" + desc: "Zincirleme 5 çağrıdan hangisinin null olduğunu artık tahmin etmek gerekmez." +- icon: "🆓" + title: "Ücretsiz yükseltme" + desc: "Kod değişikliği gerekmez — sadece JDK 14+ üzerinde çalıştırın." +support: + description: JDK 14'ten itibaren geniş çapta kullanılabilir (Mart 2020) diff --git a/translations/content/tr/errors/multi-catch.yaml b/translations/content/tr/errors/multi-catch.yaml new file mode 100644 index 0000000..0e6daeb --- /dev/null +++ b/translations/content/tr/errors/multi-catch.yaml @@ -0,0 +1,18 @@ +--- +title: Çoklu istisna yakalama +oldApproach: Ayrı Catch Blokları +modernApproach: Çoklu catch +summary: "Birden fazla istisna türünü tek bir catch bloğunda yakalayın." +explanation: "Çoklu catch, aynı kodla birden fazla istisna türünü işler. İstisna değişkeni fiilen final olduğundan, sarmalamaya gerek kalmadan yeniden fırlatılabilir." +whyModernWins: +- icon: "📏" + title: "DRY" + desc: "Aynı işlem mantığı üç kez yerine bir kez yazılır." +- icon: "🔄" + title: "Yeniden fırlatılabilir" + desc: "Yakalanan istisna, tam türüyle yeniden fırlatılabilir." +- icon: "📖" + title: "Taranabilir" + desc: "Tüm işlenen türler tek bir yerde görünür." +support: + description: JDK 7'den itibaren geniş çapta kullanılabilir (Temmuz 2011) diff --git a/translations/content/tr/errors/null-in-switch.yaml b/translations/content/tr/errors/null-in-switch.yaml new file mode 100644 index 0000000..a14f43e --- /dev/null +++ b/translations/content/tr/errors/null-in-switch.yaml @@ -0,0 +1,18 @@ +--- +title: Switch içinde null durumu +oldApproach: Switch Öncesi Koruma +modernApproach: case null +summary: "null değerini doğrudan bir switch durumu olarak işleyin — ayrı koruma gerekmez." +explanation: "Örüntü eşleştirme switch, null değerini bir durum etiketi olarak eşleştirebilir. Bu, switch öncesinde null kontrolüne olan ihtiyacı ortadan kaldırır ve null işlemeyi açık ve görünür kılar." +whyModernWins: +- icon: "🎯" + title: "Açık" + desc: "null işleme doğrudan switch içinde görünür." +- icon: "🛡️" + title: "NPE yok" + desc: "null değer üzerinde switch, NullPointerException fırlatmaz." +- icon: "📐" + title: "Hepsi bir arada" + desc: "null dahil tüm durumlar tek bir switch ifadesinde." +support: + description: JDK 21 LTS'den itibaren geniş çapta kullanılabilir (Eylül 2023) diff --git a/translations/content/tr/errors/optional-chaining.yaml b/translations/content/tr/errors/optional-chaining.yaml new file mode 100644 index 0000000..3ce23cb --- /dev/null +++ b/translations/content/tr/errors/optional-chaining.yaml @@ -0,0 +1,18 @@ +--- +title: Optional zincirleme +oldApproach: İç İçe Null Kontrolleri +modernApproach: Optional Pipeline +summary: "İç içe null kontrollerini Optional pipeline ile değiştirin." +explanation: "Optional.map(), null değerler üzerinden kısa devre yaparak zincirleme sağlar. orElse() varsayılanı sağlar. Bu, piramit şeklindeki null kontrolünü ortadan kaldırır." +whyModernWins: +- icon: "🔗" + title: "Zincirlenebilir" + desc: "Her .map() adımı null'ı şeffaf biçimde işler." +- icon: "📖" + title: "Doğrusal akış" + desc: "İç içe if blokları yerine soldan sağa okunur." +- icon: "🛡️" + title: "NPE'ye karşı korumalı" + desc: "Her adımda null işlenir — çökme mümkün değildir." +support: + description: JDK 8+'dan itibaren kullanılabilir (9+'da iyileştirildi) diff --git a/translations/content/tr/errors/optional-orelsethrow.yaml b/translations/content/tr/errors/optional-orelsethrow.yaml new file mode 100644 index 0000000..c8c601c --- /dev/null +++ b/translations/content/tr/errors/optional-orelsethrow.yaml @@ -0,0 +1,18 @@ +--- +title: Supplier olmadan Optional.orElseThrow() +oldApproach: get() veya orElseThrow(supplier) +modernApproach: orElseThrow() +summary: "get() için daha net ve niyeti açıklayan bir alternatif olarak Optional.orElseThrow() kullanın." +explanation: "Optional.get(), başarısızlık olasılığını gizlediği için yaygın biçimde kötü uygulama olarak kabul edilir. Java 10'da eklenen argümansız orElseThrow(), tam olarak aynı şeyi yapar ama niyeti açık kılar: geliştirici bir değer bekler ve yoksa istisna ister." +whyModernWins: +- icon: "📖" + title: "Kendini belgeleyen" + desc: "orElseThrow(), yokluğun beklenmedik olduğunu açıkça belirtir." +- icon: "🔒" + title: "get()'ten kaçınır" + desc: "Statik analiz araçları get()'i riskli olarak işaretler; orElseThrow() deyimseldir." +- icon: "⚡" + title: "Daha az şablon kod" + desc: "Varsayılan NoSuchElementException için supplier geçirmeye gerek yoktur." +support: + description: JDK 10'dan itibaren kullanılabilir (Mart 2018). diff --git a/translations/content/tr/errors/record-based-errors.yaml b/translations/content/tr/errors/record-based-errors.yaml new file mode 100644 index 0000000..de6abfe --- /dev/null +++ b/translations/content/tr/errors/record-based-errors.yaml @@ -0,0 +1,18 @@ +--- +title: Record tabanlı hata yanıtları +oldApproach: Map veya Ayrıntılı Sınıf +modernApproach: Hata Record'ları +summary: "Özlü, değiştirilemez hata yanıt türleri için record kullanın." +explanation: "Record'lar hata yanıtları için mükemmeldir — değiştirilemezler, karşılaştırma için yerleşik equals/hashCode'a ve günlükleme için toString'e sahiptirler. Özel yapıcılar doğrulama veya varsayılan değerler ekler." +whyModernWins: +- icon: "📏" + title: "Özlü" + desc: "Hata türlerini 30 satır yerine 3 satırda tanımlayın." +- icon: "🔒" + title: "Değiştirilemez" + desc: "Hata verileri oluşturulduktan sonra yanlışlıkla değiştirilemez." +- icon: "📋" + title: "Otomatik toString" + desc: "Günlükleme için mükemmel — tüm alanları otomatik olarak gösterir." +support: + description: JDK 16'dan itibaren geniş çapta kullanılabilir (Mart 2021) diff --git a/translations/content/tr/errors/require-nonnull-else.yaml b/translations/content/tr/errors/require-nonnull-else.yaml new file mode 100644 index 0000000..e74c7a2 --- /dev/null +++ b/translations/content/tr/errors/require-nonnull-else.yaml @@ -0,0 +1,18 @@ +--- +title: Objects.requireNonNullElse() +oldApproach: Üçlü Null Kontrolü +modernApproach: requireNonNullElse() +summary: "Üçlü operatöre gerek kalmadan net bir varsayılanla null olmayan değer elde edin." +explanation: "requireNonNullElse, ilk argüman null değilse onu döndürür, aksi takdirde ikinciyi döndürür. Varsayılanın kendisi null olamaz — her ikisi de null ise NPE fırlatarak hataları erken yakalar." +whyModernWins: +- icon: "📖" + title: "Net niyet" + desc: "Metod adı tam olarak ne yaptığını açıklar." +- icon: "🛡️" + title: "Null güvenli varsayılan" + desc: "Varsayılan değer de null açısından kontrol edilir." +- icon: "📏" + title: "Okunabilir" + desc: "Basit null-ya-da-varsayılan mantığı için üçlü operatörden daha iyidir." +support: + description: JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017) diff --git a/translations/content/tr/io/deserialization-filters.yaml b/translations/content/tr/io/deserialization-filters.yaml new file mode 100644 index 0000000..7d61224 --- /dev/null +++ b/translations/content/tr/io/deserialization-filters.yaml @@ -0,0 +1,18 @@ +--- +title: Seri duruma getirme filtreleri +oldApproach: Her Şeyi Kabul Et +modernApproach: ObjectInputFilter +summary: "Saldırıları önlemek için hangi sınıfların seri durumdan çıkarılabileceğini kısıtlayın." +explanation: "ObjectInputFilter, sınıfları izin listesine/reddetme listesine almanıza, nesne grafiği derinliğini, dizi boyutlarını ve referans sayılarını sınırlandırmanıza olanak tanır. Bu, harici kütüphaneler olmadan seri duruma getirme güvenlik açıklarına karşı koruma sağlar." +whyModernWins: +- icon: "🛡️" + title: "Güvenlik" + desc: "Beklenmedik/kötü niyetli sınıfların seri durumdan çıkarılmasını önleyin." +- icon: "📐" + title: "İnce taneli" + desc: "Derinlik, dizi boyutu, referanslar ve sınıf örüntülerini kontrol edin." +- icon: "🏗️" + title: "JVM genelinde" + desc: "JVM'deki tüm seri duruma getirme işlemleri için global filtre belirleyin." +support: + description: JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017) diff --git a/translations/content/tr/io/file-memory-mapping.yaml b/translations/content/tr/io/file-memory-mapping.yaml new file mode 100644 index 0000000..3dd7993 --- /dev/null +++ b/translations/content/tr/io/file-memory-mapping.yaml @@ -0,0 +1,18 @@ +--- +title: Dosya bellek eşleme +oldApproach: MappedByteBuffer +modernApproach: Arena ile MemorySegment +summary: "MemorySegment kullanarak 2 GB'tan büyük dosyaları belirleyici temizlemeyle eşleyin." +explanation: "Foreign Function & Memory API (JEP 454), güvenli ve verimli bellek erişimi için MemorySegment'i tanıtır. MappedByteBuffer'dan farklı olarak MemorySegment, 2 GB'tan (Integer.MAX_VALUE) büyük dosyaları destekler, Arena aracılığıyla belirleyici temizleme sağlar ve modern donanımla daha iyi performans sunar." +whyModernWins: +- icon: "📏" + title: "Boyut sınırı yok" + desc: "Geçici çözümler olmadan 2 GB'tan büyük dosyaları eşleyin." +- icon: "🔒" + title: "Belirleyici temizleme" + desc: "Arena, belleğin GC zamanında değil kapsam çıkışında serbest bırakılmasını sağlar." +- icon: "⚡" + title: "Daha iyi performans" + desc: "Modern bellek modelleri ve donanımla uyumlu." +support: + description: JDK 22'den itibaren kullanılabilir (Mart 2024) diff --git a/translations/content/tr/io/files-mismatch.yaml b/translations/content/tr/io/files-mismatch.yaml new file mode 100644 index 0000000..a856203 --- /dev/null +++ b/translations/content/tr/io/files-mismatch.yaml @@ -0,0 +1,18 @@ +--- +title: Files.mismatch() +oldApproach: Manuel Bayt Karşılaştırma +modernApproach: Files.mismatch() +summary: "İki dosyayı belleğe yüklemeden verimli biçimde karşılaştırın." +explanation: "Files.mismatch(), farklılık gösteren ilk baytın konumunu döndürür veya dosyalar özdeşse -1 döndürür. Tembel okur ve ilk farklılıkta kısa devre yapar." +whyModernWins: +- icon: "⚡" + title: "Bellek verimli" + desc: "Dosyaların tamamını bayt dizilerine yüklemez." +- icon: "🎯" + title: "Farkı tam olarak bulur" + desc: "İlk uyumsuzluğun tam bayt konumunu döndürür." +- icon: "📏" + title: "Tek çağrı" + desc: "Manuel bayt dizisi karşılaştırma mantığına gerek yoktur." +support: + description: JDK 12'den itibaren geniş çapta kullanılabilir (Mart 2019) diff --git a/translations/content/tr/io/http-client.yaml b/translations/content/tr/io/http-client.yaml new file mode 100644 index 0000000..edfb4aa --- /dev/null +++ b/translations/content/tr/io/http-client.yaml @@ -0,0 +1,18 @@ +--- +title: Modern HTTP istemcisi +oldApproach: HttpURLConnection +modernApproach: HttpClient +summary: "Temiz, modern HTTP istekleri için yerleşik HttpClient'ı kullanın." +explanation: "HttpClient, HTTP/1.1 ve HTTP/2, asenkron istekler, WebSocket, özel executor'lar ve bağlantı havuzlamayı destekler. Artık URLConnection cast etmeye veya InputStream'leri manuel olarak okumaya gerek yoktur." +whyModernWins: +- icon: "📐" + title: "Builder API" + desc: "İstekler, başlıklar ve zaman aşımları için akıcı builder." +- icon: "🔄" + title: "HTTP/2 desteği" + desc: "Çoklama ve sunucu push ile yerleşik HTTP/2." +- icon: "⚡" + title: "Asenkrona hazır" + desc: "sendAsync(), CompletableFuture döndürür." +support: + description: JDK 11'den itibaren geniş çapta kullanılabilir (Eylül 2018) diff --git a/translations/content/tr/io/inputstream-transferto.yaml b/translations/content/tr/io/inputstream-transferto.yaml new file mode 100644 index 0000000..9138644 --- /dev/null +++ b/translations/content/tr/io/inputstream-transferto.yaml @@ -0,0 +1,18 @@ +--- +title: InputStream.transferTo() +oldApproach: Manuel Kopyalama Döngüsü +modernApproach: transferTo() +summary: "Bir InputStream'i tek çağrıyla OutputStream'e kopyalayın." +explanation: "transferTo(), giriş akışındaki tüm baytları okur ve çıkış akışına yazar. Tampon yönetimi veya döngü gerekmez. Optimize edilmiş bir iç tampon kullanır." +whyModernWins: +- icon: "📏" + title: "Tek satır" + desc: "Tüm okuma/yazma döngüsünü tek bir metod çağrısıyla değiştirin." +- icon: "⚡" + title: "Optimize edilmiş" + desc: "İç tampon boyutu performans için ayarlanmıştır." +- icon: "🛡️" + title: "Hata yok" + desc: "Tampon yönetiminde tek tek kayma hatası yoktur." +support: + description: JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017) diff --git a/translations/content/tr/io/io-class-console-io.yaml b/translations/content/tr/io/io-class-console-io.yaml new file mode 100644 index 0000000..4579a46 --- /dev/null +++ b/translations/content/tr/io/io-class-console-io.yaml @@ -0,0 +1,18 @@ +--- +title: Konsol G/Ç için IO sınıfı +oldApproach: System.out / Scanner +modernApproach: IO sınıfı +summary: "Yeni IO sınıfı, konsol girişi ve çıkışı için basit ve özlü metodlar sağlar." +explanation: "Java 25, örtük olarak tanımlanan sınıflar özelliğinin bir parçası olarak IO sınıfını (java.io.IO) tanıtır. println(), print(), readln() ve read() gibi statik metodlar sağlayarak System.out ile Scanner'ın ayrıntılı kombinasyonunun yerini alır. IO.readln(prompt), tek bir çağrıda hem istem vermeyi hem de okumayı gerçekleştirir. Sınıf, kompakt kaynak dosyalarında otomatik olarak kullanılabilir ve geleneksel sınıflarda import ile kullanılabilir." +whyModernWins: +- icon: "✨" + title: "Çok daha basit" + desc: "İki metod, Scanner kurulumu, istem verme, okuma ve temizlemenin yedi satırının yerini alır." +- icon: "🔒" + title: "Kaynak sızıntısı yok" + desc: "Kapatılacak Scanner yok — IO metodları kaynak yönetimini dahili olarak halleder." +- icon: "🎓" + title: "Başlangıç dostu" + desc: "Yeni geliştiriciler Scanner, System.out veya import ifadelerini öğrenmeden konsol G/Ç yapabilir." +support: + description: "JDK 25'te örtük olarak tanımlanan sınıfların bir parçası olarak önizleme (JEP 495)" diff --git a/translations/content/tr/io/path-of.yaml b/translations/content/tr/io/path-of.yaml new file mode 100644 index 0000000..29c2efc --- /dev/null +++ b/translations/content/tr/io/path-of.yaml @@ -0,0 +1,18 @@ +--- +title: Path.of() fabrika metodu +oldApproach: Paths.get() +modernApproach: Path.of() +summary: "Path arayüzündeki modern fabrika metodu olan Path.of()'u kullanın." +explanation: "Path.of(), ayrı Paths yardımcı sınıfının yerini alarak doğrudan Path arayüzüne eklenmiş bir fabrika metodudur. Daha keşfedilebilir ve List.of(), Map.of() vb. ile tutarlıdır." +whyModernWins: +- icon: "📐" + title: "Tutarlı API" + desc: "List.of(), Set.of() gibi .of() fabrika örüntüsünü izler." +- icon: "📖" + title: "Keşfedilebilir" + desc: "Ayrı bir Paths sınıfı değil, Path türünün kendisinde bulunur." +- icon: "🧹" + title: "Bir sınıf daha az" + desc: "Paths yardımcı sınıfını import etmeye gerek yoktur." +support: + description: JDK 11'den itibaren geniş çapta kullanılabilir (Eylül 2018) diff --git a/translations/content/tr/io/reading-files.yaml b/translations/content/tr/io/reading-files.yaml new file mode 100644 index 0000000..32ef718 --- /dev/null +++ b/translations/content/tr/io/reading-files.yaml @@ -0,0 +1,18 @@ +--- +title: Dosya okuma +oldApproach: BufferedReader +modernApproach: Files.readString() +summary: "Bir dosyanın tamamını tek satırla String'e okuyun." +explanation: "Files.readString(), bir dosyanın tüm içeriğini String'e okur. Kodlamayı (varsayılan olarak UTF-8) ve kaynak temizliğini halleder. Büyük dosyalar için tembel akış amacıyla Files.lines() kullanın." +whyModernWins: +- icon: "📏" + title: "Tek satır" + desc: "8 satırlık BufferedReader şablon kodunun yerini alır." +- icon: "🧹" + title: "Otomatik temizleme" + desc: "Dosya tanıtıcısı otomatik olarak kapatılır." +- icon: "🌐" + title: "Varsayılan UTF-8" + desc: "Varsayılan olarak doğru kodlama — karakter kümesi karışıklığı yok." +support: + description: JDK 11'den itibaren geniş çapta kullanılabilir (Eylül 2018) diff --git a/translations/content/tr/io/try-with-resources-effectively-final.yaml b/translations/content/tr/io/try-with-resources-effectively-final.yaml new file mode 100644 index 0000000..b20d6d7 --- /dev/null +++ b/translations/content/tr/io/try-with-resources-effectively-final.yaml @@ -0,0 +1,18 @@ +--- +title: Try-with-resources iyileştirmesi +oldApproach: Değişkeni Yeniden Tanımla +modernApproach: Fiilen Final +summary: "Fiilen final olan mevcut değişkenleri doğrudan try-with-resources içinde kullanın." +explanation: "Java 9, fiilen final olan değişkenlerin yeniden tanımlanmadan doğrudan try-with-resources içinde kullanılmasına olanak tanır. Kaynak try bloğunun dışında oluşturulduğunda bu daha temiz bir çözümdür." +whyModernWins: +- icon: "🧹" + title: "Yeniden tanımlama yok" + desc: "Mevcut değişken adını doğrudan kullanın." +- icon: "📖" + title: "Daha az karışıklık" + desc: "Try bloğu içinde ayrı değişken adı gerekmez." +- icon: "📏" + title: "Özlü" + desc: "Daha az satır, aynı kaynak güvenliği." +support: + description: JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017) diff --git a/translations/content/tr/io/writing-files.yaml b/translations/content/tr/io/writing-files.yaml new file mode 100644 index 0000000..54fc63c --- /dev/null +++ b/translations/content/tr/io/writing-files.yaml @@ -0,0 +1,18 @@ +--- +title: Dosya yazma +oldApproach: FileWriter + BufferedWriter +modernApproach: Files.writeString() +summary: "Bir String'i tek satırla dosyaya yazın." +explanation: "Files.writeString(), içeriği varsayılan olarak UTF-8 kodlamasıyla dosyaya yazar. Ekleme, oluşturma vb. için seçenekler geçirilebilir." +whyModernWins: +- icon: "📏" + title: "Tek satır" + desc: "Writer sarmalama veya try-with-resources gerekmez." +- icon: "🛡️" + title: "Güvenli varsayılanlar" + desc: "UTF-8 kodlama, uygun dosya tanıtıcısı temizliği." +- icon: "🔧" + title: "Seçenekler" + desc: "Ekleme, oluşturma vb. için OpenOption bayrakları geçirin." +support: + description: JDK 11'den itibaren geniş çapta kullanılabilir (Eylül 2018) diff --git a/translations/content/tr/security/key-derivation-functions.yaml b/translations/content/tr/security/key-derivation-functions.yaml new file mode 100644 index 0000000..7f56103 --- /dev/null +++ b/translations/content/tr/security/key-derivation-functions.yaml @@ -0,0 +1,18 @@ +--- +title: Anahtar Türetme Fonksiyonları +oldApproach: Manuel PBKDF2 +modernApproach: KDF API +summary: "Standart KDF API'sini kullanarak kriptografik anahtarlar türetin." +explanation: "KDF API, HKDF dahil anahtar türetme fonksiyonları için standart bir arayüz sağlar. Garip SecretKeyFactory + PBEKeySpec örüntüsünü temiz bir builder API'si ile değiştirir." +whyModernWins: +- icon: "📐" + title: "Temiz API" + desc: "Garip KeySpec yapıcıları yerine builder örüntüsü." +- icon: "🔧" + title: "HKDF desteği" + desc: "PBKDF2'nin yanında modern HKDF algoritması." +- icon: "🛡️" + title: "Standart" + desc: "Tüm anahtar türetme algoritmaları için birleşik API." +support: + description: "JDK 25 LTS'de sonuçlandırıldı (JEP 510, Eylül 2025)." diff --git a/translations/content/tr/security/pem-encoding.yaml b/translations/content/tr/security/pem-encoding.yaml new file mode 100644 index 0000000..8d4a77e --- /dev/null +++ b/translations/content/tr/security/pem-encoding.yaml @@ -0,0 +1,18 @@ +--- +title: PEM kodlama/çözme +oldApproach: Manuel Base64 + Başlıklar +modernApproach: PEM API +summary: "Kriptografik nesneleri yerel olarak PEM formatında kodlayın ve çözün." +explanation: "PEM API, sertifikalar, anahtarlar ve diğer kriptografik nesneler için PEM formatında standart kodlama/çözme sağlar. Artık BEGIN/END başlıklarıyla manuel Base64 sarmalamaya gerek yoktur." +whyModernWins: +- icon: "🧹" + title: "Manuel Base64 yok" + desc: "PEM başlıkları, satır sarmalama ve Base64 otomatik olarak işlenir." +- icon: "🔄" + title: "İki yönlü" + desc: "Tek bir API ile PEM'e kodlama ve PEM'den çözme." +- icon: "🛡️" + title: "Standart format" + desc: "RFC 7468 uyumlu PEM çıktısı üretir." +support: + description: "JDK 25'te önizleme (JEP 470). --enable-preview gerektirir." diff --git a/translations/content/tr/security/random-generator.yaml b/translations/content/tr/security/random-generator.yaml new file mode 100644 index 0000000..b807dbf --- /dev/null +++ b/translations/content/tr/security/random-generator.yaml @@ -0,0 +1,18 @@ +--- +title: RandomGenerator arayüzü +oldApproach: new Random() / ThreadLocalRandom +modernApproach: RandomGenerator fabrikası +summary: "Belirli bir sınıfa bağlı kalmadan rastgele sayı algoritmalarını ada göre seçmek için RandomGenerator arayüzünü kullanın." +explanation: "JDK 17, tüm RNG uygulamaları için ortak arayüz olarak RandomGenerator'ı tanıttı. new Random() veya ThreadLocalRandom'ı sabit kodlamak yerine, farklı kullanım durumları için optimize edilmiş algoritmalar arasında kolayca geçiş yapmayı sağlayan bir fabrika aracılığıyla ada göre algoritma seçebilirsiniz (hız, istatistiksel kalite, bölünebilirlik)." +whyModernWins: +- icon: "🔧" + title: "Algoritmadan bağımsız" + desc: "Kod yapısını değiştirmeden en iyi RNG algoritmasını ada göre seçin." +- icon: "⚡" + title: "Daha iyi algoritmalar" + desc: "Üstün istatistiksel özelliklere sahip modern LXM üreticilerine erişim." +- icon: "🔗" + title: "Birleşik API" + desc: "Tek arayüz; Random, ThreadLocalRandom, SplittableRandom ve daha fazlasını kapsar." +support: + description: "JDK 17'den itibaren kullanılabilir (Eylül 2021, JEP 356)." diff --git a/translations/content/tr/security/strong-random.yaml b/translations/content/tr/security/strong-random.yaml new file mode 100644 index 0000000..a5889e0 --- /dev/null +++ b/translations/content/tr/security/strong-random.yaml @@ -0,0 +1,18 @@ +--- +title: Güçlü rastgele üretim +oldApproach: new SecureRandom() +modernApproach: getInstanceStrong() +summary: "Platformun en güçlü SecureRandom uygulamasını edinin." +explanation: "getInstanceStrong(), platformda en güçlü olarak yapılandırılan SecureRandom uygulamasını döndürür. Bu, securerandom.strongAlgorithms güvenlik özelliği tarafından kontrol edilir." +whyModernWins: +- icon: "🛡️" + title: "Mevcut en güçlüsü" + desc: "Platform için en iyi algoritmayı otomatik olarak seçer." +- icon: "📖" + title: "Açık niyet" + desc: "Güçlü rastgeleliğin gerekli olduğunu açıkça belirtir." +- icon: "🔧" + title: "Yapılandırılabilir" + desc: "Yöneticiler güvenlik özellikleri aracılığıyla güçlü algoritmayı değiştirebilir." +support: + description: JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017) diff --git a/translations/content/tr/security/tls-default.yaml b/translations/content/tr/security/tls-default.yaml new file mode 100644 index 0000000..a3913c8 --- /dev/null +++ b/translations/content/tr/security/tls-default.yaml @@ -0,0 +1,18 @@ +--- +title: Varsayılan olarak TLS 1.3 +oldApproach: Manuel TLS Yapılandırması +modernApproach: Varsayılan TLS 1.3 +summary: "TLS 1.3 varsayılan olarak etkindir — açık protokol yapılandırmasına gerek yoktur." +explanation: "Java 11, TLS 1.3 desteğini ekledi ve onu tercih edilen protokol yaptı. HttpClient bunu otomatik olarak kullanır. Güvenli bağlantılar için artık protokol sürümlerini manuel olarak belirtmeye gerek yoktur." +whyModernWins: +- icon: "🛡️" + title: "Daha güvenli" + desc: "TLS 1.3, eski şifre paketlerini ve el sıkışma örüntülerini kaldırır." +- icon: "⚡" + title: "Daha hızlı el sıkışma" + desc: "TLS 1.3, iki yerine tek bir gidip gelişte tamamlanır." +- icon: "🆓" + title: "Sıfır yapılandırma" + desc: "Varsayılan olarak güvenli — açık protokol seçimine gerek yoktur." +support: + description: JDK 11'den itibaren geniş çapta kullanılabilir (Eylül 2018) From 706e75ac6e020ccd5f4517dc72311ac9030de42b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:43:04 +0000 Subject: [PATCH 22/28] Add Turkish (tr) translations for language category (22 files) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../compact-canonical-constructor.yaml | 18 ++++++++++++++++++ .../tr/language/compact-source-files.yaml | 18 ++++++++++++++++++ .../tr/language/default-interface-methods.yaml | 18 ++++++++++++++++++ .../content/tr/language/diamond-operator.yaml | 18 ++++++++++++++++++ .../content/tr/language/exhaustive-switch.yaml | 18 ++++++++++++++++++ .../language/flexible-constructor-bodies.yaml | 18 ++++++++++++++++++ .../content/tr/language/guarded-patterns.yaml | 18 ++++++++++++++++++ .../tr/language/markdown-javadoc-comments.yaml | 18 ++++++++++++++++++ .../language/module-import-declarations.yaml | 18 ++++++++++++++++++ .../language/pattern-matching-instanceof.yaml | 18 ++++++++++++++++++ .../tr/language/pattern-matching-switch.yaml | 18 ++++++++++++++++++ .../language/primitive-types-in-patterns.yaml | 18 ++++++++++++++++++ .../tr/language/private-interface-methods.yaml | 18 ++++++++++++++++++ .../content/tr/language/record-patterns.yaml | 18 ++++++++++++++++++ .../tr/language/records-for-data-classes.yaml | 18 ++++++++++++++++++ .../content/tr/language/sealed-classes.yaml | 18 ++++++++++++++++++ .../static-members-in-inner-classes.yaml | 18 ++++++++++++++++++ .../language/static-methods-in-interfaces.yaml | 18 ++++++++++++++++++ .../tr/language/switch-expressions.yaml | 18 ++++++++++++++++++ .../text-blocks-for-multiline-strings.yaml | 18 ++++++++++++++++++ .../tr/language/type-inference-with-var.yaml | 18 ++++++++++++++++++ .../content/tr/language/unnamed-variables.yaml | 18 ++++++++++++++++++ 22 files changed, 396 insertions(+) create mode 100644 translations/content/tr/language/compact-canonical-constructor.yaml create mode 100644 translations/content/tr/language/compact-source-files.yaml create mode 100644 translations/content/tr/language/default-interface-methods.yaml create mode 100644 translations/content/tr/language/diamond-operator.yaml create mode 100644 translations/content/tr/language/exhaustive-switch.yaml create mode 100644 translations/content/tr/language/flexible-constructor-bodies.yaml create mode 100644 translations/content/tr/language/guarded-patterns.yaml create mode 100644 translations/content/tr/language/markdown-javadoc-comments.yaml create mode 100644 translations/content/tr/language/module-import-declarations.yaml create mode 100644 translations/content/tr/language/pattern-matching-instanceof.yaml create mode 100644 translations/content/tr/language/pattern-matching-switch.yaml create mode 100644 translations/content/tr/language/primitive-types-in-patterns.yaml create mode 100644 translations/content/tr/language/private-interface-methods.yaml create mode 100644 translations/content/tr/language/record-patterns.yaml create mode 100644 translations/content/tr/language/records-for-data-classes.yaml create mode 100644 translations/content/tr/language/sealed-classes.yaml create mode 100644 translations/content/tr/language/static-members-in-inner-classes.yaml create mode 100644 translations/content/tr/language/static-methods-in-interfaces.yaml create mode 100644 translations/content/tr/language/switch-expressions.yaml create mode 100644 translations/content/tr/language/text-blocks-for-multiline-strings.yaml create mode 100644 translations/content/tr/language/type-inference-with-var.yaml create mode 100644 translations/content/tr/language/unnamed-variables.yaml diff --git a/translations/content/tr/language/compact-canonical-constructor.yaml b/translations/content/tr/language/compact-canonical-constructor.yaml new file mode 100644 index 0000000..f2f4a5d --- /dev/null +++ b/translations/content/tr/language/compact-canonical-constructor.yaml @@ -0,0 +1,18 @@ +--- +title: Kompakt kanonik constructor +oldApproach: Açık constructor doğrulaması +modernApproach: Kompakt constructor +summary: "Record alanlarını parametre listelerini tekrar etmeden doğrulayın ve normalleştirin." +explanation: "Record'lar, parametre listesini ve alan atamalarını atlayan kompakt kanonik constructor tanımlayabilir. Derleyici, doğrulama mantığınız çalıştıktan sonra parametreleri alanlara otomatik olarak atar. Bu, ön koşul kontrolleri, savunmacı kopyalar ve normalleştirme için idealdir." +whyModernWins: +- icon: "✂️" + title: Daha az tekrar + desc: "Parametre listesini tekrar etmeye veya her alanı elle atamaya gerek yoktur." +- icon: "🛡️" + title: Doğrulama + desc: "Null kontrolleri, aralık doğrulaması ve savunmacı kopyalar için mükemmeldir." +- icon: "📖" + title: Daha net niyet + desc: "Kompakt sözdizimi, şablon kodları değil doğrulamayı ön plana çıkarır." +support: + description: JDK 16'dan itibaren geniş çapta kullanılabilir (Mart 2021) diff --git a/translations/content/tr/language/compact-source-files.yaml b/translations/content/tr/language/compact-source-files.yaml new file mode 100644 index 0000000..51e8106 --- /dev/null +++ b/translations/content/tr/language/compact-source-files.yaml @@ -0,0 +1,18 @@ +--- +title: Kompakt kaynak dosyaları +oldApproach: Ana Sınıf Tören Kodu +modernApproach: void main() +summary: "Sınıf bildirimi veya public static void main olmadan eksiksiz bir program yazın." +explanation: "Kompakt kaynak dosyaları, basit programlar için sınıf bildirimleri ve main metot imzasının törenini ortadan kaldırır. java.io.IO'nun örtük içe aktarımıyla birlikte println bile doğrudan kullanılabilir." +whyModernWins: +- icon: "🚀" + title: Sıfır tören + desc: "Sınıf yok, public static void main yok, String[] args yok." +- icon: "🎓" + title: Yeni başlayanlar için uygun + desc: "Yeni programcılar 1. satırdan itibaren kullanışlı kod yazabilir." +- icon: "📝" + title: Betik benzeri + desc: "Hızlı prototipler, betikler ve örnekler için mükemmeldir." +support: + description: "JDK 25 LTS'de tamamlandı (JEP 512, Eylül 2025)." diff --git a/translations/content/tr/language/default-interface-methods.yaml b/translations/content/tr/language/default-interface-methods.yaml new file mode 100644 index 0000000..c16632c --- /dev/null +++ b/translations/content/tr/language/default-interface-methods.yaml @@ -0,0 +1,18 @@ +--- +title: Varsayılan interface metotları +oldApproach: Paylaşılan davranış için soyut sınıflar +modernApproach: Interface'lerde varsayılan metotlar +summary: "Metot implementasyonlarını doğrudan interface'lere ekleyin ve çoklu davranış kalıtımını etkinleştirin." +explanation: "Java 8'den önce, ilgisiz sınıflar arasında davranış paylaşmak soyut sınıflar gerektiriyordu ve bu da sizi tek kalıtımla sınırlıyordu. Varsayılan metotlar, interface'lerin metot implementasyonları sağlamasına izin verir, böylece sınıflar birden fazla interface'den davranış kalıtımı alabilir. Bu, mevcut implementasyonları bozmadan Koleksiyonlar API'sini (örn. List.forEach, Map.getOrDefault) geliştirmek için gerekliydi." +whyModernWins: +- icon: "🔀" + title: Çoklu kalıtım + desc: "Sınıflar, tek soyut sınıf kalıtımının aksine, varsayılan metotlara sahip birçok interface'i uygulayabilir." +- icon: "📦" + title: API evrimi + desc: "Mevcut implementasyonları bozmadan interface'lere yeni metotlar ekleyin." +- icon: "🧩" + title: Birleştirilebilir davranış + desc: "Birden fazla interface'den yetenekleri özgürce karıştırın ve eşleştirin." +support: + description: "JDK 8'den itibaren kullanılabilir (Mart 2014)." diff --git a/translations/content/tr/language/diamond-operator.yaml b/translations/content/tr/language/diamond-operator.yaml new file mode 100644 index 0000000..6f67eb6 --- /dev/null +++ b/translations/content/tr/language/diamond-operator.yaml @@ -0,0 +1,18 @@ +--- +title: Anonim sınıflarla elmas operatörü +oldApproach: Tür Argümanlarını Tekrarlayın +modernApproach: "Elmas <>" +summary: "Elmas operatörü artık anonim sınıflarla da çalışır." +explanation: "Java 7, <> operatörünü tanıttı ancak anonim iç sınıflarla çalışmıyordu. Java 9 bunu düzeltti, böylece sağ tarafta tür argümanlarını asla tekrar etmeniz gerekmez." +whyModernWins: +- icon: "📏" + title: Tutarlı kurallar + desc: "Elmas her yerde çalışır — hem constructor'larda hem anonim sınıflarda." +- icon: "🧹" + title: Daha az tekrar + desc: "Tür argümanları solda bir kez belirtilir, asla tekrarlanmaz." +- icon: "🔧" + title: DRY ilkesi + desc: "Derleyici türü zaten biliyor — neden iki kez yazasınız ki?" +support: + description: "Anonim sınıflarla elmas operatörü JDK 9'dan itibaren kullanılabilir (Eylül 2017)." diff --git a/translations/content/tr/language/exhaustive-switch.yaml b/translations/content/tr/language/exhaustive-switch.yaml new file mode 100644 index 0000000..d1c2328 --- /dev/null +++ b/translations/content/tr/language/exhaustive-switch.yaml @@ -0,0 +1,18 @@ +--- +title: Varsayılan olmadan kapsamlı switch +oldApproach: Zorunlu default +modernApproach: sealed Kapsamlılığı +summary: "Derleyici tüm sealed alt türlerin kapsandığını doğrular — default gerekmez." +explanation: "Sealed bir türde switch kullandığınızda, derleyici tüm olası alt türleri bilir ve her durumun işlendiğini doğrular. Yeni bir alt tür eklerseniz, derleyici artık eksik olan her switch'i işaretler." +whyModernWins: +- icon: "✅" + title: Derleme zamanı güvenliği + desc: "Yeni bir alt tür ekleyin ve derleyici güncellenecek her yeri gösterir." +- icon: "🚫" + title: Ölü kod yok + desc: "Hataları gizleyen erişilemeyen varsayılan dal yoktur." +- icon: "📐" + title: Cebirsel türler + desc: "sealed + record'lar + kapsamlı switch = Java'da uygun ADT'ler." +support: + description: "JDK 21 LTS'den itibaren geniş çapta kullanılabilir (Eylül 2023)" diff --git a/translations/content/tr/language/flexible-constructor-bodies.yaml b/translations/content/tr/language/flexible-constructor-bodies.yaml new file mode 100644 index 0000000..3975f10 --- /dev/null +++ b/translations/content/tr/language/flexible-constructor-bodies.yaml @@ -0,0 +1,18 @@ +--- +title: Esnek constructor gövdeleri +oldApproach: "super()'dan Sonra Doğrula" +modernApproach: "super()'dan Önce Kod" +summary: "super() veya this() çağırmadan önce değerleri doğrulayın ve hesaplayın." +explanation: "Java 25, super()'ın ilk deyim olması zorunluluğunu kaldırır. Artık üst sınıf constructor'ına devretmeden önce argümanları doğrulayabilir, türetilmiş değerler hesaplayabilir ve durumu ayarlayabilirsiniz." +whyModernWins: +- icon: "🛡️" + title: Hızla başarısız ol + desc: "super() constructor çalışmadan önce argümanları doğrulayın." +- icon: "🧮" + title: Önce hesapla + desc: "super() çağırmadan önce değerleri türetin ve verileri hazırlayın." +- icon: "🧹" + title: Geçici çözüm yok + desc: "Kısıtlamayı aşmak için artık statik yardımcı metotlar veya fabrika kalıpları gerekmiyor." +support: + description: "JDK 25 LTS'de tamamlandı (JEP 513, Eylül 2025)." diff --git a/translations/content/tr/language/guarded-patterns.yaml b/translations/content/tr/language/guarded-patterns.yaml new file mode 100644 index 0000000..4419887 --- /dev/null +++ b/translations/content/tr/language/guarded-patterns.yaml @@ -0,0 +1,18 @@ +--- +title: when ile korumalı kalıplar +oldApproach: İç içe if +modernApproach: when Cümlesi +summary: "when koruyucularını kullanarak kalıp durumlarına koşullar ekleyin." +explanation: "Korumalı kalıplar, bir tür eşleşmesini ek bir boolean koşuluyla rafine etmenizi sağlar. Bu, durumların içinde if deyimlerini iç içe koymak yerine tüm dallanma mantığını switch içinde tutar." +whyModernWins: +- icon: "🎯" + title: Hassas eşleştirme + desc: "Tek bir case etiketinde tür + koşulu birleştirin." +- icon: "📐" + title: Düz yapı + desc: "switch durumları içinde iç içe if/else yoktur." +- icon: "📖" + title: Okunabilir niyet + desc: "when cümlesi doğal dil gibi okunur." +support: + description: "JDK 21 LTS'den itibaren geniş çapta kullanılabilir (Eylül 2023)" diff --git a/translations/content/tr/language/markdown-javadoc-comments.yaml b/translations/content/tr/language/markdown-javadoc-comments.yaml new file mode 100644 index 0000000..f19f4c8 --- /dev/null +++ b/translations/content/tr/language/markdown-javadoc-comments.yaml @@ -0,0 +1,18 @@ +--- +title: Javadoc yorumlarında Markdown +oldApproach: HTML tabanlı Javadoc +modernApproach: Markdown Javadoc +summary: "Daha iyi okunabilirlik için Javadoc yorumlarını HTML yerine Markdown ile yazın." +explanation: "Java 23, geleneksel /** */ HTML tabanlı biçime alternatif olarak /// Markdown stilinde Javadoc yorumlarını tanıtır. Markdown sözdizimi yazmak ve okumak için daha doğaldır; kod blokları, vurgu, listeler ve bağlantılar için destek sunar. Derleyici, javadoc çıktısı için Markdown'ı HTML'ye dönüştürür." +whyModernWins: +- icon: "📖" + title: Doğal sözdizimi + desc: "HTML etiketleri yerine satır içi kod için backtick ve bloklar için ``` kullanın." +- icon: "✍️" + title: Yazmak daha kolay + desc: "{@code},
, 

etiketlerine gerek yok — sadece Markdown yazın." +- icon: "👁" + title: Editörlerde daha iyi + desc: "Markdown, modern IDE'lerde ve metin editörlerinde güzel bir şekilde görüntülenir." +support: + description: "JDK 23'ten itibaren kullanılabilir (Eylül 2024)" diff --git a/translations/content/tr/language/module-import-declarations.yaml b/translations/content/tr/language/module-import-declarations.yaml new file mode 100644 index 0000000..8d9fdcf --- /dev/null +++ b/translations/content/tr/language/module-import-declarations.yaml @@ -0,0 +1,18 @@ +--- +title: Modül içe aktarım bildirimleri +oldApproach: Çok Sayıda İçe Aktarım +modernApproach: import module +summary: "Bir modülün dışa aktardığı tüm paketleri tek bir bildirimle içe aktarın." +explanation: "Modül içe aktarım bildirimleri, bir modülün dışa aktardığı her şeyi tek bir satırla içe aktarmanıza izin verir. Bu, özellikle koleksiyonları, G/Ç'yi, akışları ve daha fazlasını kapsayan java.base için kullanışlıdır." +whyModernWins: +- icon: "🧹" + title: Tek satır + desc: "Uzun içe aktarım listesini tek bir modül içe aktarımıyla değiştirin." +- icon: "📦" + title: Modüle duyarlı + desc: "Tutarlı paket kümelerini içe aktarmak için modül sistemini kullanır." +- icon: "🚀" + title: Hızlı başlangıç + desc: "İçe aktarım listelerinin sıkıcı olduğu betikler ve prototipler için mükemmeldir." +support: + description: "JDK 25 LTS'de tamamlandı (JEP 511, Eylül 2025)." diff --git a/translations/content/tr/language/pattern-matching-instanceof.yaml b/translations/content/tr/language/pattern-matching-instanceof.yaml new file mode 100644 index 0000000..c840043 --- /dev/null +++ b/translations/content/tr/language/pattern-matching-instanceof.yaml @@ -0,0 +1,18 @@ +--- +title: instanceof için kalıp eşleştirme +oldApproach: instanceof + Tür Dönüşümü +modernApproach: Kalıp Değişkeni +summary: "Tür kontrolü ve tür dönüşümünü kalıp eşleştirme ile tek adımda birleştirin." +explanation: "instanceof için kalıp eşleştirme, tür kontrolünden sonra gereksiz tür dönüşümünü ortadan kaldırır. Değişken, kalıbın eşleştiği yerle otomatik olarak kapsamlandırılır; bu da kodu daha güvenli ve kısa yapar." +whyModernWins: +- icon: "🔄" + title: Gereksiz tür dönüşümü yok + desc: "Tür kontrolü ve değişken bağlama tek bir ifadede gerçekleşir." +- icon: "📏" + title: Daha az satır + desc: "İki satır yerine bir satır — tür dönüşümü satırı tamamen ortadan kalkar." +- icon: "🛡️" + title: Kapsam güvenliği + desc: "Kalıp değişkeni yalnızca türün garanti edildiği yerde kapsamdadır." +support: + description: "JDK 16'dan itibaren geniş çapta kullanılabilir (Mart 2021)" diff --git a/translations/content/tr/language/pattern-matching-switch.yaml b/translations/content/tr/language/pattern-matching-switch.yaml new file mode 100644 index 0000000..3544a7b --- /dev/null +++ b/translations/content/tr/language/pattern-matching-switch.yaml @@ -0,0 +1,18 @@ +--- +title: switch'te kalıp eşleştirme +oldApproach: if-else Zinciri +modernApproach: Tür Kalıpları +summary: "if-else instanceof zincirlerini temiz switch tür kalıplarıyla değiştirin." +explanation: "switch'te kalıp eşleştirme, tür testini, tür dönüşümünü ve bağlamayı tek ve özlü bir case etiketinde birleştirerek türlere doğrudan eşleştirmenizi sağlar. Derleyici tamamlığı denetler." +whyModernWins: +- icon: "📐" + title: Yapılandırılmış dağıtım + desc: "switch, dallanma yapısını açık ve taranabilir hale getirir." +- icon: "🎯" + title: İfade biçimi + desc: "Doğrudan bir değer döndürür — değiştirilebilir değişkene gerek yoktur." +- icon: "✅" + title: Kapsamlılık + desc: "Derleyici tüm türlerin işlendiğini sağlar." +support: + description: "JDK 21 LTS'den itibaren geniş çapta kullanılabilir (Eylül 2023)" diff --git a/translations/content/tr/language/primitive-types-in-patterns.yaml b/translations/content/tr/language/primitive-types-in-patterns.yaml new file mode 100644 index 0000000..95ad6c0 --- /dev/null +++ b/translations/content/tr/language/primitive-types-in-patterns.yaml @@ -0,0 +1,18 @@ +--- +title: Kalıplarda temel türler +oldApproach: Manuel Aralık Kontrolleri +modernApproach: Temel Tür Kalıpları +summary: "Kalıp eşleştirme artık yalnızca nesnelerle değil, temel türlerle de çalışır." +explanation: "Java 25, kalıp eşleştirmeyi temel türlere genişletir. int, long, double vb. türleri when koruyucularıyla switch kalıplarında kullanabilirsiniz; bu, kutulama veya manuel aralık kontrollerine olan ihtiyacı ortadan kaldırır." +whyModernWins: +- icon: "📦" + title: Kutulama yok + desc: "Temel türleri doğrudan eşleştirin — Integer sarmalayıcısına gerek yoktur." +- icon: "🎯" + title: Kalıp tutarlılığı + desc: "Nesneler ve temel türler için aynı kalıp sözdizimi." +- icon: "⚡" + title: Daha iyi performans + desc: "Kalıp eşleştirmede otomatik kutulama yükünü önleyin." +support: + description: "JDK 25'te önizleme (üçüncü önizleme, JEP 507). --enable-preview gerektirir." diff --git a/translations/content/tr/language/private-interface-methods.yaml b/translations/content/tr/language/private-interface-methods.yaml new file mode 100644 index 0000000..05ccc6d --- /dev/null +++ b/translations/content/tr/language/private-interface-methods.yaml @@ -0,0 +1,18 @@ +--- +title: Özel interface metotları +oldApproach: Çoğaltılmış Mantık +modernApproach: Özel Metotlar +summary: "Özel metotlar kullanarak interface'lerdeki paylaşılan mantığı çıkarın." +explanation: "Java 9, interface'lerde özel metotlara izin vererek uygulama ayrıntılarını uygulayan sınıflara göstermeden varsayılan metotlar arasında kod paylaşmanıza olanak tanır." +whyModernWins: +- icon: "🧩" + title: Kod yeniden kullanımı + desc: "Tekrar etmeden varsayılan metotlar arasında mantığı paylaşın." +- icon: "🔐" + title: Kapsülleme + desc: "Uygulama ayrıntıları uygulayan sınıflardan gizli kalır." +- icon: "🧹" + title: DRY interface'ler + desc: "Varsayılan metotlar arasında artık kopyala-yapıştır yok." +support: + description: "JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017)" diff --git a/translations/content/tr/language/record-patterns.yaml b/translations/content/tr/language/record-patterns.yaml new file mode 100644 index 0000000..9bb26e0 --- /dev/null +++ b/translations/content/tr/language/record-patterns.yaml @@ -0,0 +1,18 @@ +--- +title: "Record kalıpları (parçalama)" +oldApproach: Manuel Erişim +modernApproach: Parçalama +summary: "Record'ları doğrudan kalıplarda parçalayın — alanları tek adımda çıkarın." +explanation: "Record kalıpları, bir record'un bileşenlerini doğrudan instanceof ve switch içinde ayrıştırmanıza olanak tanır. İç içe kalıplar da desteklenir; bu, ara değişkenler olmadan derin eşleştirmeyi mümkün kılar." +whyModernWins: +- icon: "🎯" + title: Doğrudan çıkarma + desc: "Erişimcileri elle çağırmadan record bileşenlerine erişin." +- icon: "🪆" + title: İç içe geçirilebilir + desc: "Kalıplar iç içe geçirilebilir — tek bir ifadede iç record'larla eşleştirin." +- icon: "📏" + title: Kompakt kod + desc: "Beş satır ikiye dönüşür — daha az tören, aynı netlik." +support: + description: "JDK 21 LTS'den itibaren geniş çapta kullanılabilir (Eylül 2023)" diff --git a/translations/content/tr/language/records-for-data-classes.yaml b/translations/content/tr/language/records-for-data-classes.yaml new file mode 100644 index 0000000..b346807 --- /dev/null +++ b/translations/content/tr/language/records-for-data-classes.yaml @@ -0,0 +1,18 @@ +--- +title: Veri sınıfları için record'lar +oldApproach: Ayrıntılı POJO +modernApproach: record +summary: "Bir satır, değişmez veri taşıyıcılar için 30'dan fazla satır şablon kodunun yerini alır." +explanation: "Record'lar constructor'ı, erişimcileri (x(), y()), equals(), hashCode() ve toString() metodlarını otomatik olarak oluşturur. Tasarım gereği değişmezdirler ve DTO'lar, değer nesneleri ve kalıp eşleştirme için idealdir." +whyModernWins: +- icon: "⚡" + title: Tek satır tanım + desc: "Tek satır constructor, getter'lar, equals, hashCode, toString'in yerini alır." +- icon: "🔒" + title: Varsayılan olarak değişmez + desc: "Tüm alanlar final'dır — setter tuzağı yoktur." +- icon: "🧩" + title: Kalıp dostu + desc: "Record'lar switch ve instanceof'ta parçalama kalıplarıyla çalışır." +support: + description: "JDK 16'dan itibaren geniş çapta kullanılabilir (Mart 2021)" diff --git a/translations/content/tr/language/sealed-classes.yaml b/translations/content/tr/language/sealed-classes.yaml new file mode 100644 index 0000000..9384f7a --- /dev/null +++ b/translations/content/tr/language/sealed-classes.yaml @@ -0,0 +1,18 @@ +--- +title: Tür hiyerarşileri için sealed sınıflar +oldApproach: Açık Hiyerarşi +modernApproach: sealed permits +summary: "Hangi sınıfların bir türü genişletebileceğini kısıtlayın — kapsamlı switch'leri etkinleştirin." +explanation: "Sealed sınıflar, kapalı bir alt tür kümesi tanımlar. Derleyici tüm olası durumları bilir ve varsayılan bir dal olmadan kapsamlı kalıp eşleştirmeyi etkinleştirir. Record'larla birleştirildiğinde cebirsel veri türlerini modeller." +whyModernWins: +- icon: "🔐" + title: Kontrollü hiyerarşi + desc: "Yalnızca izin verilen alt türler genişletebilir — sürpriz alt sınıf yok." +- icon: "✅" + title: Kapsamlı eşleştirme + desc: "Derleyici switch'in tüm durumları kapsadığını doğrular, default gerekmez." +- icon: "📐" + title: Cebirsel veri türleri + desc: "Sum türlerini doğal olarak modelleyin — sealed + record'lar = Java'da ADT'ler." +support: + description: "JDK 17 LTS'den itibaren geniş çapta kullanılabilir (Eylül 2021)" diff --git a/translations/content/tr/language/static-members-in-inner-classes.yaml b/translations/content/tr/language/static-members-in-inner-classes.yaml new file mode 100644 index 0000000..59ec5a5 --- /dev/null +++ b/translations/content/tr/language/static-members-in-inner-classes.yaml @@ -0,0 +1,18 @@ +--- +title: İç sınıflardaki statik üyeler +oldApproach: Statik iç içe sınıf kullanılmalı +modernApproach: İç sınıflarda statik üyeler +summary: "Statik iç içe sınıflar gerektirmeden iç sınıflarda statik üyeler tanımlayın." +explanation: "Java 16'dan önce, yalnızca statik iç içe sınıflar statik üyeler içerebiliyordu. İç (statik olmayan) sınıflar, bir çevreleyen örnek gerektirdiğinden statik üyelere sahip olamazdı. Java 16, bu kısıtlamayı gevşeterek iç sınıflarda statik alanlar, metotlar ve hatta iç içe türlere izin verir." +whyModernWins: +- icon: "🔓" + title: Daha fazla esneklik + desc: "İç sınıflar artık gerektiğinde statik üyelere sahip olabilir." +- icon: "🧩" + title: Paylaşılan durum + desc: "Bir iç sınıfın örnekleri arasında paylaşılan durumu takip edin." +- icon: "📐" + title: Tasarım özgürlüğü + desc: "Yalnızca bir statik alan için statik iç içe sınıfa geçmeye gerek yok." +support: + description: "JDK 16'dan itibaren geniş çapta kullanılabilir (Mart 2021)" diff --git a/translations/content/tr/language/static-methods-in-interfaces.yaml b/translations/content/tr/language/static-methods-in-interfaces.yaml new file mode 100644 index 0000000..2934e08 --- /dev/null +++ b/translations/content/tr/language/static-methods-in-interfaces.yaml @@ -0,0 +1,18 @@ +--- +title: Interface'lerde statik metotlar +oldApproach: Yardımcı sınıflar +modernApproach: Interface statik metotları +summary: "Ayrı yardımcı sınıflar yerine statik yardımcı metotları doğrudan interface'lere ekleyin." +explanation: "Java 8'den önce, bir interface ile ilgili yardımcı metotlar ayrı bir sınıfta (örn. Collection için Collections) yaşamak zorundaydı. Interface'lerdeki statik metotlar, ilgili yardımcı araçları bir arada tutmanızı sağlar. Comparator.comparing(), Stream.of() ve List.of() gibi modern API'lerde yaygındır." +whyModernWins: +- icon: "📦" + title: Daha iyi organizasyon + desc: "İlgili yardımcı araçları ayrı bir sınıfta değil, interface ile birlikte tutun." +- icon: "🔍" + title: Keşfedilebilirlik + desc: "Fabrika ve yardımcı metotlar, onları beklediğiniz yerde bulunur." +- icon: "🧩" + title: API uyumu + desc: "Ayrı *Utils veya *Helper sınıflarına gerek yoktur." +support: + description: "JDK 8'den itibaren kullanılabilir (Mart 2014)" diff --git a/translations/content/tr/language/switch-expressions.yaml b/translations/content/tr/language/switch-expressions.yaml new file mode 100644 index 0000000..0c0340c --- /dev/null +++ b/translations/content/tr/language/switch-expressions.yaml @@ -0,0 +1,18 @@ +--- +title: Switch ifadeleri +oldApproach: Switch Deyimi +modernApproach: Switch İfadesi +summary: "Değer döndüren switch ifadesi — break yok, düşme geçişi yok." +explanation: "Switch ifadeleri doğrudan bir değer döndürür, düşme geçişi hatalarını önlemek için ok sözdizimini kullanır ve derleyici kapsamlılığı doğrular. Bu, hataya açık deyim biçiminin yerini alır." +whyModernWins: +- icon: "🎯" + title: Değer döndürür + desc: "Switch sonucunu doğrudan atayın — geçici değişkene gerek yoktur." +- icon: "🛡️" + title: Düşme geçişi yok + desc: "Ok sözdizimi, eksik break nedeniyle oluşan yanlışlıkla düşme geçişi hatalarını ortadan kaldırır." +- icon: "✅" + title: Kapsamlılık kontrolü + desc: "Derleyici tüm durumların kapsandığını sağlar." +support: + description: "JDK 14'ten itibaren geniş çapta kullanılabilir (Mart 2020)" diff --git a/translations/content/tr/language/text-blocks-for-multiline-strings.yaml b/translations/content/tr/language/text-blocks-for-multiline-strings.yaml new file mode 100644 index 0000000..d70e6ac --- /dev/null +++ b/translations/content/tr/language/text-blocks-for-multiline-strings.yaml @@ -0,0 +1,18 @@ +--- +title: Çok satırlı dizeler için metin blokları +oldApproach: String Birleştirme +modernApproach: Metin Blokları +summary: "Üçlü tırnak metin blokları ile çok satırlı dizeleri doğal olarak yazın." +explanation: "Metin blokları, çok satırlı dizeleri tam olarak göründükleri gibi yazmanıza olanak tanır. Artık tırnak işaretlerini kaçırmak veya \\n eklemek gerekmez. Derleyici, gereksiz girintiyi otomatik olarak kaldırır." +whyModernWins: +- icon: "📖" + title: Olduğu gibi okunabilir + desc: "JSON, SQL ve HTML, kaynak kodunuzda gerçek JSON, SQL ve HTML gibi görünür." +- icon: "🚫" + title: Kaçış cehennemi yok + desc: "Gömülü tırnak işaretleri ters eğik çizgi ile kaçırılmaya gerek yoktur." +- icon: "📐" + title: Akıllı girinti + desc: "Başlangıç boşluğu, kapanış sınırlayıcı konumuna göre otomatik olarak kırpılır." +support: + description: "JDK 15'ten itibaren geniş çapta kullanılabilir (Eylül 2020)" diff --git a/translations/content/tr/language/type-inference-with-var.yaml b/translations/content/tr/language/type-inference-with-var.yaml new file mode 100644 index 0000000..fdb6e85 --- /dev/null +++ b/translations/content/tr/language/type-inference-with-var.yaml @@ -0,0 +1,18 @@ +--- +title: var ile tür çıkarımı +oldApproach: Açık Türler +modernApproach: var anahtar kelimesi +summary: "Yerel değişken tür çıkarımı için var kullanın — daha az gürültü, aynı güvenlik." +explanation: "Java 10'dan itibaren, derleyici yerel değişken türlerini sağ taraftan çıkarır. Bu, tür güvenliğinden ödün vermeden görsel gürültüyü azaltır. Türün bağlamdan açık olduğu durumlarda var kullanın." +whyModernWins: +- icon: "⚡" + title: Daha az şablon kod + desc: "Atamanın her iki tarafında karmaşık genel türleri tekrar etmeye gerek yoktur." +- icon: "👁" + title: Daha iyi okunabilirlik + desc: "Tür bildirimlerine değil, değişken adlarına ve değerlere odaklanın." +- icon: "🔒" + title: Hâlâ tür güvenli + desc: "Derleyici, derleme zamanında tam türü çıkarır ve uygular." +support: + description: "JDK 10'dan itibaren geniş çapta kullanılabilir (Mart 2018)" diff --git a/translations/content/tr/language/unnamed-variables.yaml b/translations/content/tr/language/unnamed-variables.yaml new file mode 100644 index 0000000..063fcd9 --- /dev/null +++ b/translations/content/tr/language/unnamed-variables.yaml @@ -0,0 +1,18 @@ +--- +title: _ ile isimsiz değişkenler +oldApproach: Kullanılmayan Değişken +modernApproach: _ Yer Tutucu +summary: "Bir değişkenin kasıtlı olarak kullanılmadığını belirtmek için _ kullanın." +explanation: "İsimsiz değişkenler, okuyuculara ve araçlara bir değerin kasıtlı olarak görmezden gelindiğini iletir. Artık 'ignored' veya 'unused' adlandırma kurallarına, artık IDE uyarılarına gerek yoktur." +whyModernWins: +- icon: "📢" + title: Net niyet + desc: "_ açıkça 'bu değere burada ihtiyaç yok' der." +- icon: "🔇" + title: Uyarı yok + desc: "IDE'ler ve lint araçları kasıtlı olarak kullanılmayan değişkenleri işaretlemez." +- icon: "🧹" + title: Daha temiz lambda'lar + desc: "Çok parametreli lambda'lar yalnızca bazı parametrelere ihtiyaç duyduğunuzda daha temizdir." +support: + description: "JDK 22'de tamamlandı (JEP 456, Mart 2024)." From df8f4a8a6bb0249006898b9870974d2264835004 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:46:56 +0000 Subject: [PATCH 23/28] Add Turkish (tr) translations for streams, strings, and tooling patterns - 11 streams files: collectors-flatmapping, optional-ifpresentorelse, optional-or, predicate-not, stream-gatherers, stream-iterate-predicate, stream-mapmulti, stream-of-nullable, stream-takewhile-dropwhile, stream-tolist, virtual-thread-executor - 7 strings files: string-chars-stream, string-formatted, string-indent-transform, string-isblank, string-lines, string-repeat, string-strip - 8 tooling files: aot-class-preloading, built-in-http-server, compact-object-headers, jfr-profiling, jshell-prototyping, junit6-with-jspecify, multi-file-source, single-file-execution Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../tr/streams/collectors-flatmapping.yaml | 18 ++++++++++++++++++ .../tr/streams/optional-ifpresentorelse.yaml | 18 ++++++++++++++++++ .../content/tr/streams/optional-or.yaml | 18 ++++++++++++++++++ .../content/tr/streams/predicate-not.yaml | 18 ++++++++++++++++++ .../content/tr/streams/stream-gatherers.yaml | 18 ++++++++++++++++++ .../tr/streams/stream-iterate-predicate.yaml | 18 ++++++++++++++++++ .../content/tr/streams/stream-mapmulti.yaml | 18 ++++++++++++++++++ .../content/tr/streams/stream-of-nullable.yaml | 18 ++++++++++++++++++ .../tr/streams/stream-takewhile-dropwhile.yaml | 18 ++++++++++++++++++ .../content/tr/streams/stream-tolist.yaml | 18 ++++++++++++++++++ .../tr/streams/virtual-thread-executor.yaml | 18 ++++++++++++++++++ .../tr/strings/string-chars-stream.yaml | 18 ++++++++++++++++++ .../content/tr/strings/string-formatted.yaml | 18 ++++++++++++++++++ .../tr/strings/string-indent-transform.yaml | 18 ++++++++++++++++++ .../content/tr/strings/string-isblank.yaml | 18 ++++++++++++++++++ .../content/tr/strings/string-lines.yaml | 18 ++++++++++++++++++ .../content/tr/strings/string-repeat.yaml | 18 ++++++++++++++++++ .../content/tr/strings/string-strip.yaml | 18 ++++++++++++++++++ .../tr/tooling/aot-class-preloading.yaml | 18 ++++++++++++++++++ .../tr/tooling/built-in-http-server.yaml | 18 ++++++++++++++++++ .../tr/tooling/compact-object-headers.yaml | 18 ++++++++++++++++++ .../content/tr/tooling/jfr-profiling.yaml | 18 ++++++++++++++++++ .../content/tr/tooling/jshell-prototyping.yaml | 18 ++++++++++++++++++ .../tr/tooling/junit6-with-jspecify.yaml | 18 ++++++++++++++++++ .../content/tr/tooling/multi-file-source.yaml | 18 ++++++++++++++++++ .../tr/tooling/single-file-execution.yaml | 18 ++++++++++++++++++ 26 files changed, 468 insertions(+) create mode 100644 translations/content/tr/streams/collectors-flatmapping.yaml create mode 100644 translations/content/tr/streams/optional-ifpresentorelse.yaml create mode 100644 translations/content/tr/streams/optional-or.yaml create mode 100644 translations/content/tr/streams/predicate-not.yaml create mode 100644 translations/content/tr/streams/stream-gatherers.yaml create mode 100644 translations/content/tr/streams/stream-iterate-predicate.yaml create mode 100644 translations/content/tr/streams/stream-mapmulti.yaml create mode 100644 translations/content/tr/streams/stream-of-nullable.yaml create mode 100644 translations/content/tr/streams/stream-takewhile-dropwhile.yaml create mode 100644 translations/content/tr/streams/stream-tolist.yaml create mode 100644 translations/content/tr/streams/virtual-thread-executor.yaml create mode 100644 translations/content/tr/strings/string-chars-stream.yaml create mode 100644 translations/content/tr/strings/string-formatted.yaml create mode 100644 translations/content/tr/strings/string-indent-transform.yaml create mode 100644 translations/content/tr/strings/string-isblank.yaml create mode 100644 translations/content/tr/strings/string-lines.yaml create mode 100644 translations/content/tr/strings/string-repeat.yaml create mode 100644 translations/content/tr/strings/string-strip.yaml create mode 100644 translations/content/tr/tooling/aot-class-preloading.yaml create mode 100644 translations/content/tr/tooling/built-in-http-server.yaml create mode 100644 translations/content/tr/tooling/compact-object-headers.yaml create mode 100644 translations/content/tr/tooling/jfr-profiling.yaml create mode 100644 translations/content/tr/tooling/jshell-prototyping.yaml create mode 100644 translations/content/tr/tooling/junit6-with-jspecify.yaml create mode 100644 translations/content/tr/tooling/multi-file-source.yaml create mode 100644 translations/content/tr/tooling/single-file-execution.yaml diff --git a/translations/content/tr/streams/collectors-flatmapping.yaml b/translations/content/tr/streams/collectors-flatmapping.yaml new file mode 100644 index 0000000..3a1f70a --- /dev/null +++ b/translations/content/tr/streams/collectors-flatmapping.yaml @@ -0,0 +1,18 @@ +--- +title: "Collectors.flatMapping()" +oldApproach: İç içe flatMap +modernApproach: "flatMapping()" +summary: "Gruplama toplayıcısının içinde düzleştirme yapmak için flatMapping() kullanın." +explanation: "Collectors.flatMapping(), bir bire-çok eşlemeyi aşağı akış toplayıcısı olarak uygular. Stream.flatMap() işlevinin toplayıcı karşılığıdır — groupingBy veya partitioningBy içinde kullanışlıdır." +whyModernWins: +- icon: "🧩" + title: Birleştirilebilir + desc: "groupingBy içinde aşağı akış toplayıcısı olarak çalışır." +- icon: "📐" + title: Tek geçiş + desc: "Tek bir akış geçişinde düzleştirme ve gruplama yapılır." +- icon: "🔗" + title: İç içe kullanılabilir + desc: "Diğer aşağı akış toplayıcılarıyla birleştirilebilir." +support: + description: "JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017)" diff --git a/translations/content/tr/streams/optional-ifpresentorelse.yaml b/translations/content/tr/streams/optional-ifpresentorelse.yaml new file mode 100644 index 0000000..4b4e12d --- /dev/null +++ b/translations/content/tr/streams/optional-ifpresentorelse.yaml @@ -0,0 +1,18 @@ +--- +title: "Optional.ifPresentOrElse()" +oldApproach: Optional üzerinde if/else +modernApproach: "ifPresentOrElse()" +summary: "Optional'ın hem mevcut hem de boş durumlarını tek bir çağrıda işleyin." +explanation: "ifPresentOrElse(), mevcut durum için bir Consumer ve boş durum için bir Runnable alır. isPresent/get anti-deseninden kaçınılmasını sağlar." +whyModernWins: +- icon: "📏" + title: Tek ifade + desc: "Her iki durum tek bir metot çağrısında işlenir." +- icon: "🚫" + title: "get() yok" + desc: "Tehlikeli isPresent() + get() desenini ortadan kaldırır." +- icon: "🔗" + title: Akıcı + desc: "findUser() veya Optional döndüren herhangi bir metodun ardından doğal olarak zincirlenir." +support: + description: "JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017)" diff --git a/translations/content/tr/streams/optional-or.yaml b/translations/content/tr/streams/optional-or.yaml new file mode 100644 index 0000000..e730365 --- /dev/null +++ b/translations/content/tr/streams/optional-or.yaml @@ -0,0 +1,18 @@ +--- +title: "Optional.or() ile yedekleme" +oldApproach: İç içe yedekleme +modernApproach: ".or() zinciri" +summary: "İç içe kontroller olmadan Optional yedeklerini zincirleyin." +explanation: "Optional.or(), orijinal Optional'ın bir değeri varsa onu döndürür; yoksa alternatif bir Optional elde etmek için tedarikçiyi değerlendirir. Tedarikçiler gecikmeli çalışır — yalnızca gerektiğinde çağrılır." +whyModernWins: +- icon: "🔗" + title: Zincirlenebilir + desc: "Okunabilir bir boru hattında yedekler arka arkaya eklenir." +- icon: "⚡" + title: Gecikmeli değerlendirme + desc: "Yedek tedarikçiler yalnızca gerekli olduğunda çalışır." +- icon: "📖" + title: Bildirimsel + desc: "'önce birincili dene, yoksa ikincili, yoksa varsayılanı' şeklinde okunur." +support: + description: "JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017)" diff --git a/translations/content/tr/streams/predicate-not.yaml b/translations/content/tr/streams/predicate-not.yaml new file mode 100644 index 0000000..2e95db8 --- /dev/null +++ b/translations/content/tr/streams/predicate-not.yaml @@ -0,0 +1,18 @@ +--- +title: "Predicate.not() ile olumsuzlama" +oldApproach: Lambda olumsuzlama +modernApproach: "Predicate.not()" +summary: "Lambda sarmalayıcılar yazmak yerine metot referanslarını temiz biçimde olumsuzlamak için Predicate.not() kullanın." +explanation: "Java 11'den önce bir metot referansını olumsuzlamak için onu bir lambda içine sarmak gerekiyordu. Predicate.not(), herhangi bir koşulu doğrudan olumsuzlamanıza olanak tanır; bu sayede kod okunabilirliği korunur ve akış hattı boyunca metot referansı stiliyle tutarlılık sağlanır." +whyModernWins: +- icon: "👁" + title: Daha temiz olumsuzlama + desc: "Metot referanslarını olumsuzlamak için lambda içine sarmaya gerek kalmaz." +- icon: "🔗" + title: Birleştirilebilir + desc: "Her Predicate ile çalışır; temiz koşul zincirleri oluşturmayı sağlar." +- icon: "📖" + title: Doğal okunur + desc: "Predicate.not(String::isBlank) İngilizce gibi okunur." +support: + description: "JDK 11'den itibaren kullanılabilir (Eylül 2018)." diff --git a/translations/content/tr/streams/stream-gatherers.yaml b/translations/content/tr/streams/stream-gatherers.yaml new file mode 100644 index 0000000..8dd8bbe --- /dev/null +++ b/translations/content/tr/streams/stream-gatherers.yaml @@ -0,0 +1,18 @@ +--- +title: Stream toplayıcıları +oldApproach: Özel Collector +modernApproach: "gather()" +summary: "Özel ara akış işlemleri için toplayıcılar kullanın." +explanation: "Toplayıcılar (Gatherers), kayan pencereler, sabit boyutlu gruplar ve standart akış işlemleriyle mümkün olmayan tarama işlemleri gibi karmaşık dönüşümleri ifade edebilen yeni bir ara akış işlemidir." +whyModernWins: +- icon: "🧩" + title: Birleştirilebilir + desc: "Toplayıcılar diğer akış işlemleriyle birleştirilebilir." +- icon: "📦" + title: Yerleşik işlemler + desc: "windowFixed, windowSliding, fold ve scan kullanıma hazır gelir." +- icon: "🔧" + title: Genişletilebilir + desc: "Herhangi bir ara dönüşüm için özel toplayıcılar yazılabilir." +support: + description: "JDK 24'te tamamlandı (JEP 485, Mart 2025)." diff --git a/translations/content/tr/streams/stream-iterate-predicate.yaml b/translations/content/tr/streams/stream-iterate-predicate.yaml new file mode 100644 index 0000000..023eaf0 --- /dev/null +++ b/translations/content/tr/streams/stream-iterate-predicate.yaml @@ -0,0 +1,18 @@ +--- +title: "Koşullu Stream.iterate()" +oldApproach: iterate + limit +modernApproach: "iterate(seed, pred, op)" +summary: "Akış biçiminde bir döngü gibi yinelemeyi durdurmak için koşul kullanın." +explanation: "Üç argümanlı Stream.iterate(seed, hasNext, next), bir for döngüsü gibi çalışır: seed başlangıç değeri, hasNext ne zaman duracağını belirler ve next sonraki değeri üretir." +whyModernWins: +- icon: "🎯" + title: Doğal sonlandırma + desc: "Keyfi bir sınır değil, bir koşula göre durun." +- icon: "📐" + title: "for döngüsü karşılığı" + desc: "for(seed; hasNext; next) ile aynı anlambilim." +- icon: "🛡️" + title: Sonsuz akış riski yok + desc: "Koşul, sonlandırmayı garanti eder." +support: + description: "JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017)" diff --git a/translations/content/tr/streams/stream-mapmulti.yaml b/translations/content/tr/streams/stream-mapmulti.yaml new file mode 100644 index 0000000..fc89d78 --- /dev/null +++ b/translations/content/tr/streams/stream-mapmulti.yaml @@ -0,0 +1,18 @@ +--- +title: "Stream.mapMulti()" +oldApproach: "flatMap + List" +modernApproach: "mapMulti()" +summary: "Ara akışlar oluşturmadan her giriş için sıfır veya daha fazla öğe yayın." +explanation: "mapMulti(), her öğe için ara Stream nesneleri oluşturmaktan kaçınan, flatMap'e alternatif bir zorunlu yöntemdir. Eşlemenin az sayıda öğe ürettiği durumlarda daha verimlidir." +whyModernWins: +- icon: "⚡" + title: Daha az bellek kullanımı + desc: "Her öğe için ara Stream oluşturulmaz." +- icon: "🎯" + title: Zorunlu stil + desc: "Döngüler ve koşullar doğrudan kullanılabilir." +- icon: "📐" + title: Esnek + desc: "Tam denetimle sıfır, bir veya çok sayıda öğe yayılabilir." +support: + description: "JDK 16'dan itibaren geniş çapta kullanılabilir (Mart 2021)" diff --git a/translations/content/tr/streams/stream-of-nullable.yaml b/translations/content/tr/streams/stream-of-nullable.yaml new file mode 100644 index 0000000..289f1ae --- /dev/null +++ b/translations/content/tr/streams/stream-of-nullable.yaml @@ -0,0 +1,18 @@ +--- +title: "Stream.ofNullable()" +oldApproach: Null Kontrolü +modernApproach: "ofNullable()" +summary: "Null olabilecek bir değerden sıfır veya bir öğeli akış oluşturun." +explanation: "Stream.ofNullable(), değer null değilse tek öğeli, null ise boş bir akış döndürür. Üçlü null kontrol desenini ortadan kaldırır." +whyModernWins: +- icon: "📏" + title: Özlü + desc: "Tek bir çağrı üçlü koşulun yerini alır." +- icon: "🔗" + title: "flatMap uyumlu" + desc: "flatMap içinde null değerleri atlamak için mükemmeldir." +- icon: "🛡️" + title: Null-güvenli + desc: "NPE riski yok — null boş akışa dönüşür." +support: + description: "JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017)" diff --git a/translations/content/tr/streams/stream-takewhile-dropwhile.yaml b/translations/content/tr/streams/stream-takewhile-dropwhile.yaml new file mode 100644 index 0000000..c899e0e --- /dev/null +++ b/translations/content/tr/streams/stream-takewhile-dropwhile.yaml @@ -0,0 +1,18 @@ +--- +title: "Stream takeWhile / dropWhile" +oldApproach: Manuel Döngü +modernApproach: takeWhile/dropWhile +summary: "Bir koşula göre akıştan öğeleri alın veya atlayın." +explanation: "takeWhile(), koşul doğru olduğu sürece öğeleri döndürür ve ilk yanlışta durur. dropWhile() ise koşul doğru olduğu sürece öğeleri atlar ve kalanları döndürür. Her ikisi de sıralı akışlarda en iyi çalışır." +whyModernWins: +- icon: "🎯" + title: Kısa devre + desc: "Koşul başarısız olduğunda işlemi durur." +- icon: "🔗" + title: Boru hattı uyumlu + desc: "Diğer akış işlemleriyle doğal biçimde zincirlenir." +- icon: "📖" + title: Bildirimsel + desc: "takeWhile 'koşul sağlandığı sürece al' şeklinde okunur." +support: + description: "JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017)" diff --git a/translations/content/tr/streams/stream-tolist.yaml b/translations/content/tr/streams/stream-tolist.yaml new file mode 100644 index 0000000..b4a82d7 --- /dev/null +++ b/translations/content/tr/streams/stream-tolist.yaml @@ -0,0 +1,18 @@ +--- +title: "Stream.toList()" +oldApproach: "Collectors.toList()" +modernApproach: ".toList()" +summary: "Terminal toList(), ayrıntılı collect(Collectors.toList()) çağrısının yerini alır." +explanation: "Stream.toList(), değiştirilemez bir liste döndürür. .collect(Collectors.toUnmodifiableList()) ile eşdeğerdir ancak çok daha kısadır. Not: Collectors.toList()'in aksine sonuç sabittir." +whyModernWins: +- icon: "📏" + title: "7 karakter, 24 değil" + desc: ".toList(), .collect(Collectors.toList()) ifadesinin yerini alır." +- icon: "🔒" + title: Değiştirilemez + desc: "Sonuç liste değiştirilemez." +- icon: "📖" + title: Akıcı + desc: "Boru hattının sonunda doğal biçimde okunur." +support: + description: "JDK 16'dan itibaren geniş çapta kullanılabilir (Mart 2021)" diff --git a/translations/content/tr/streams/virtual-thread-executor.yaml b/translations/content/tr/streams/virtual-thread-executor.yaml new file mode 100644 index 0000000..e8ee19b --- /dev/null +++ b/translations/content/tr/streams/virtual-thread-executor.yaml @@ -0,0 +1,18 @@ +--- +title: Sanal iş parçacığı yürütücüsü +oldApproach: Sabit İş Parçacığı Havuzu +modernApproach: Sanal İş Parçacığı Yürütücüsü +summary: "Sınırsız hafif eşzamanlılık için sanal iş parçacığı yürütücülerini kullanın." +explanation: "Sanal iş parçacığı yürütücüsü her görev için yeni bir sanal iş parçacığı oluşturur. Havuz boyutlandırması gerekmez — sanal iş parçacıkları milyonlarca oluşturulabilecek kadar ucuzdur." +whyModernWins: +- icon: "♾️" + title: Boyutlandırma yok + desc: "Ayarlanacak havuz boyutu yok — gerektiği kadar iş parçacığı oluşturulabilir." +- icon: "⚡" + title: Hafif + desc: "Sanal iş parçacıkları MB değil, KB bellek kullanır." +- icon: "🧹" + title: Otomatik kapatma + desc: "try-with-resources kapatmayı otomatik olarak yönetir." +support: + description: "JDK 21 LTS'den itibaren geniş çapta kullanılabilir (Eylül 2023)" diff --git a/translations/content/tr/strings/string-chars-stream.yaml b/translations/content/tr/strings/string-chars-stream.yaml new file mode 100644 index 0000000..b0e7cca --- /dev/null +++ b/translations/content/tr/strings/string-chars-stream.yaml @@ -0,0 +1,18 @@ +--- +title: Karakter akışı olarak String +oldApproach: Manuel Döngü +modernApproach: "chars() Stream" +summary: "Metin karakterlerini bir akış hattı olarak işleyin." +explanation: "String.chars(), karakter değerlerinden oluşan bir IntStream döndürerek işlevsel işlemeye olanak tanır. Unicode desteği için codePoints(), ek karakterleri doğru biçimde işler." +whyModernWins: +- icon: "🔗" + title: Zincirlenebilir + desc: "Karakter akışları üzerinde filter, map ve collect kullanılabilir." +- icon: "📐" + title: Bildirimsel + desc: "Nasıl döngü kurulacağını değil, ne yapılacağını tanımlayın." +- icon: "🌐" + title: "Unicode'a hazır" + desc: "codePoints(), emoji ve ek karakterleri doğru şekilde işler." +support: + description: "JDK 8+'dan itibaren kullanılabilir (9+'da geliştirildi)" diff --git a/translations/content/tr/strings/string-formatted.yaml b/translations/content/tr/strings/string-formatted.yaml new file mode 100644 index 0000000..fa793bc --- /dev/null +++ b/translations/content/tr/strings/string-formatted.yaml @@ -0,0 +1,18 @@ +--- +title: "String.formatted()" +oldApproach: "String.format()" +modernApproach: "formatted()" +summary: "formatted() metodunu şablon dizesinin kendisi üzerinde çağırın." +explanation: "String.formatted(), String.format() ile eşdeğer bir örnek metodudur; ancak biçim dizesi üzerinde çağrılır. Soldan sağa bir akışta daha doğal okunur." +whyModernWins: +- icon: "📖" + title: Doğal okunur + desc: "Template.formatted(args), String.format(template, args)'tan daha akıcı akar." +- icon: "🔗" + title: Zincirlenebilir + desc: "Diğer String metodlarıyla zincirlenebilir." +- icon: "📏" + title: Daha az ayrıntılı + desc: "Gereksiz String.format() statik çağrısını kaldırır." +support: + description: "JDK 15'ten itibaren geniş çapta kullanılabilir (Eylül 2020)" diff --git a/translations/content/tr/strings/string-indent-transform.yaml b/translations/content/tr/strings/string-indent-transform.yaml new file mode 100644 index 0000000..6767324 --- /dev/null +++ b/translations/content/tr/strings/string-indent-transform.yaml @@ -0,0 +1,18 @@ +--- +title: "String.indent() ve transform()" +oldApproach: Manuel Girintileme +modernApproach: "indent() / transform()" +summary: "Metni girintileyin ve dize dönüşümlerini akıcı biçimde zincirleyin." +explanation: "indent(n), her satıra n boşluk ekler. transform(fn) herhangi bir işlev uygular ve sonucu döndürerek dize işlemlerinin akıcı biçimde zincir oluşturmasını sağlar." +whyModernWins: +- icon: "📏" + title: Yerleşik + desc: "Girintileme yaygın bir işlemdir — artık tek bir çağrıdır." +- icon: "🔗" + title: Zincirlenebilir + desc: "transform(), dizeler üzerinde akıcı boru hatları sağlar." +- icon: "🧹" + title: Temiz kod + desc: "Manuel satır bölme ve StringBuilder döngülerine gerek kalmaz." +support: + description: "JDK 12'den itibaren geniş çapta kullanılabilir (Mart 2019)" diff --git a/translations/content/tr/strings/string-isblank.yaml b/translations/content/tr/strings/string-isblank.yaml new file mode 100644 index 0000000..22b5c01 --- /dev/null +++ b/translations/content/tr/strings/string-isblank.yaml @@ -0,0 +1,18 @@ +--- +title: "String.isBlank()" +oldApproach: "trim().isEmpty()" +modernApproach: "isBlank()" +summary: "Tek bir metot çağrısıyla boş dizeleri kontrol edin." +explanation: "isBlank(), dize boşsa veya yalnızca trim()'in kaçırdığı Unicode boşluk karakterleri de dahil olmak üzere boşluk içeriyorsa true döndürür." +whyModernWins: +- icon: "📖" + title: Kendi kendini belgeler + desc: "isBlank(), neyi kontrol ettiğini tam olarak ifade eder." +- icon: "🌐" + title: "Unicode-bilinçli" + desc: "Yalnızca ASCII değil, tüm Unicode boşluklarını işler." +- icon: "⚡" + title: Bellek tahsisi yok + desc: "Ara kırpılmış dize oluşturulmaz." +support: + description: "JDK 11'den itibaren geniş çapta kullanılabilir (Eylül 2018)" diff --git a/translations/content/tr/strings/string-lines.yaml b/translations/content/tr/strings/string-lines.yaml new file mode 100644 index 0000000..666d3bc --- /dev/null +++ b/translations/content/tr/strings/string-lines.yaml @@ -0,0 +1,18 @@ +--- +title: "String.lines() ile satır bölme" +oldApproach: "split(\"\\\\n\")" +modernApproach: "lines()" +summary: "Regex yükü olmadan metni satırlara bölmek için String.lines() kullanın." +explanation: "String.lines(), \\n, \\r veya \\r\\n ile bölünmüş satırlardan oluşan bir Stream döndürür. split()'ten daha tembel ve verimlidir; regex derlenmesinden kaçınır ve daha ileri işleme için Stream API ile doğal biçimde entegre olur." +whyModernWins: +- icon: "⚡" + title: Tembel akış + desc: "Satırlar, split() gibi hepsi bir anda değil, isteğe bağlı olarak üretilir." +- icon: "🔧" + title: Evrensel satır sonları + desc: "\\n, \\r ve \\r\\n otomatik olarak regex olmadan işlenir." +- icon: "🔗" + title: Stream entegrasyonu + desc: "filter, map ve collect ile doğrudan kullanım için Stream döndürür." +support: + description: "JDK 11'den itibaren kullanılabilir (Eylül 2018)." diff --git a/translations/content/tr/strings/string-repeat.yaml b/translations/content/tr/strings/string-repeat.yaml new file mode 100644 index 0000000..2ba88e7 --- /dev/null +++ b/translations/content/tr/strings/string-repeat.yaml @@ -0,0 +1,18 @@ +--- +title: "String.repeat()" +oldApproach: StringBuilder Döngüsü +modernApproach: "repeat()" +summary: "Bir dizeyi döngü kullanmadan n kez tekrarlayın." +explanation: "String.repeat(int), dizeyi kendisiyle n kez birleştirerek döndürür. Sınır durumlarını işler: repeat(0) boş dize, repeat(1) aynı dizeyi döndürür." +whyModernWins: +- icon: "📏" + title: Tek satır + desc: "5 satır StringBuilder kodunu tek bir çağrıyla değiştirin." +- icon: "⚡" + title: Optimize edilmiş + desc: "Dahili uygulama büyük tekrarlar için optimize edilmiştir." +- icon: "📖" + title: Net amaç + desc: "repeat(3) amacı hemen ortaya koyar." +support: + description: "JDK 11'den itibaren geniş çapta kullanılabilir (Eylül 2018)" diff --git a/translations/content/tr/strings/string-strip.yaml b/translations/content/tr/strings/string-strip.yaml new file mode 100644 index 0000000..c2e12fa --- /dev/null +++ b/translations/content/tr/strings/string-strip.yaml @@ -0,0 +1,18 @@ +--- +title: "String.strip() ve trim() karşılaştırması" +oldApproach: "trim()" +modernApproach: "strip()" +summary: "strip(), stripLeading() ve stripTrailing() ile Unicode'a duyarlı boşluk temizleme kullanın." +explanation: "trim(), yalnızca U+0020 ve altındaki karakterleri (ASCII kontrol karakterleri ve boşluk) kaldırır. strip(), bölünemez boşluk ve ideografik boşluk gibi Unicode boşluklarını da işleyen Character.isWhitespace() kullanır." +whyModernWins: +- icon: "🌐" + title: "Unicode-doğru" + desc: "Her dilden tüm boşluk karakterlerini işler." +- icon: "🎯" + title: Yönlü + desc: "stripLeading() ve stripTrailing(), tek taraflı kırpma sağlar." +- icon: "🛡️" + title: Daha az hata + desc: "Uluslararası metinlerde geride kalan sürpriz boşluk kalmaz." +support: + description: "JDK 11'den itibaren geniş çapta kullanılabilir (Eylül 2018)" diff --git a/translations/content/tr/tooling/aot-class-preloading.yaml b/translations/content/tr/tooling/aot-class-preloading.yaml new file mode 100644 index 0000000..4209f90 --- /dev/null +++ b/translations/content/tr/tooling/aot-class-preloading.yaml @@ -0,0 +1,18 @@ +--- +title: AOT sınıf ön yükleme +oldApproach: Her Seferinde Soğuk Başlangıç +modernApproach: AOT Önbelleği +summary: "Anında başlangıç için sınıf yükleme ve derlemeyi önbelleğe alın." +explanation: "AOT sınıf ön yükleme, eğitim çalışmasından yüklenen ve bağlanan sınıfları önbelleğe alır. Sonraki başlangıçlarda sınıflar önbellekten yüklenerek doğrulama ve bağlama adımları atlanır. AOT derlemesiyle birleştirildiğinde başlangıç süresi önemli ölçüde azalır." +whyModernWins: +- icon: "⚡" + title: Daha hızlı başlangıç + desc: "Sınıf yükleme, doğrulama ve bağlama adımları atlanır." +- icon: "📦" + title: Önbelleğe alınmış durum + desc: "Eğitim çalışması ideal sınıf durumunu yakalar." +- icon: "🔧" + title: Kod değişikliği gerekmez + desc: "Mevcut uygulamalarla çalışır — yalnızca JVM bayrakları eklenir." +support: + description: "JDK 25 LTS'de standart özellik olarak kullanılabilir (JEP 514/515, Eylül 2025)." diff --git a/translations/content/tr/tooling/built-in-http-server.yaml b/translations/content/tr/tooling/built-in-http-server.yaml new file mode 100644 index 0000000..37c3984 --- /dev/null +++ b/translations/content/tr/tooling/built-in-http-server.yaml @@ -0,0 +1,18 @@ +--- +title: Yerleşik HTTP sunucusu +oldApproach: Harici Sunucu / Çerçeve +modernApproach: jwebserver CLI +summary: "Java 18, prototipleme ve dosya sunumu için yerleşik minimal bir HTTP sunucusu içerir." +explanation: "JDK 18, jwebserver komut satırı aracı veya SimpleFileServer API aracılığıyla erişilebilen basit, sıfır bağımlılıklı bir HTTP dosya sunucusu ekledi. Belirli bir dizindeki statik dosyaları yapılandırma gerekmeksizin sunar. CLI aracı hızlı prototipleme, test etme ve geçici dosya paylaşımı için idealdir — harici bağımlılık veya çerçeve gerekmez. API, özelleştirilebilir işleyiciler ve çıktı seviyeleriyle programlı kullanıma olanak tanır." +whyModernWins: +- icon: "🚀" + title: Sıfır kurulum + desc: "Herhangi bir dizinde jwebserver komutunu çalıştırın — kurulum, yapılandırma veya bağımlılık gerekmez." +- icon: "📦" + title: JDK'ya dahil + desc: "Her JDK 18+ kurulumunda gelir; Java yüklü her makinede kullanılabilir." +- icon: "🧪" + title: Prototipleme için harika + desc: "HTML, API veya ön uç geliştirmeyi test etmek için statik dosyaları anında sunun." +support: + description: "JDK 18'den itibaren kullanılabilir (Mart 2022)" diff --git a/translations/content/tr/tooling/compact-object-headers.yaml b/translations/content/tr/tooling/compact-object-headers.yaml new file mode 100644 index 0000000..1a9f8a2 --- /dev/null +++ b/translations/content/tr/tooling/compact-object-headers.yaml @@ -0,0 +1,18 @@ +--- +title: Kompakt nesne başlıkları +oldApproach: 128 bit Başlıklar +modernApproach: 64 bit Başlıklar +summary: "Daha iyi bellek yoğunluğu ve önbellek kullanımı için nesne başlık boyutunu yarıya indirin." +explanation: "Kompakt nesne başlıkları, 64 bit platformlarda nesne başına ek yükü 128 bitten 64 bite düşürür. Bu durum belleği tasarruf eder ve özellikle çok sayıda küçük nesne içeren uygulamalarda önbellek kullanımını iyileştirir." +whyModernWins: +- icon: "📦" + title: "%50 daha küçük başlıklar" + desc: "Nesne başına 16 yerine 8 bayt." +- icon: "⚡" + title: Daha iyi önbellek kullanımı + desc: "CPU önbellek satırlarına daha fazla nesne sığar." +- icon: "📊" + title: Daha yüksek yoğunluk + desc: "Aynı heap boyutuna daha fazla nesne yerleştirin." +support: + description: "JDK 25 LTS'de tamamlandı (JEP 519, Eylül 2025)." diff --git a/translations/content/tr/tooling/jfr-profiling.yaml b/translations/content/tr/tooling/jfr-profiling.yaml new file mode 100644 index 0000000..be72259 --- /dev/null +++ b/translations/content/tr/tooling/jfr-profiling.yaml @@ -0,0 +1,18 @@ +--- +title: Profilleme için JFR +oldApproach: Harici Profil Aracı +modernApproach: Java Flight Recorder +summary: "Herhangi bir Java uygulamasını yerleşik Flight Recorder ile profilleyin — harici araç gerekmez." +explanation: "Java Flight Recorder (JFR), JVM'e yerleşik düşük ek yüklü bir profilleme aracıdır. CPU, bellek, GC, G/Ç, iş parçacıkları ve özel olaylar için minimal performans etkisiyle (~%1) olayları yakalar." +whyModernWins: +- icon: "🆓" + title: Yerleşik + desc: "Kurulacak veya lisanslanacak harici profil aracı yok." +- icon: "⚡" + title: Düşük ek yük + desc: "~%1 performans etkisi — üretimde kullanıma güvenli." +- icon: "📊" + title: Zengin olaylar + desc: "CPU, bellek, GC, iş parçacıkları, G/Ç, kilitler ve özel olaylar." +support: + description: "JDK 9/11'den itibaren geniş çapta kullanılabilir (11'de açık kaynak yapıldı)" diff --git a/translations/content/tr/tooling/jshell-prototyping.yaml b/translations/content/tr/tooling/jshell-prototyping.yaml new file mode 100644 index 0000000..ca288ce --- /dev/null +++ b/translations/content/tr/tooling/jshell-prototyping.yaml @@ -0,0 +1,18 @@ +--- +title: Prototipleme için JShell +oldApproach: "Dosya Oluştur + Derle + Çalıştır" +modernApproach: jshell REPL +summary: "Dosya oluşturmadan Java ifadelerini etkileşimli olarak deneyin." +explanation: "JShell, Java için bir Oku-Değerlendir-Yazdır Döngüsüdür. Dosya oluşturmak, derlemek veya main metodu yazmak zorunda kalmadan ifadeleri test edin, API'leri deneyin ve kod prototipleri oluşturun. Sekme tamamlama ve satır içi belgeler dahildir." +whyModernWins: +- icon: "⚡" + title: Anında geri bildirim + desc: "Bir ifade yazın, sonucu hemen görün." +- icon: "📝" + title: Dosya gerekmez + desc: ".java dosyası veya derleme adımı gerekmez." +- icon: "🔍" + title: API keşfi + desc: "Sekme tamamlama, metot ve parametreleri keşfetmeye yardımcı olur." +support: + description: "JDK 9'dan itibaren geniş çapta kullanılabilir (Eylül 2017)" diff --git a/translations/content/tr/tooling/junit6-with-jspecify.yaml b/translations/content/tr/tooling/junit6-with-jspecify.yaml new file mode 100644 index 0000000..e0188ec --- /dev/null +++ b/translations/content/tr/tooling/junit6-with-jspecify.yaml @@ -0,0 +1,18 @@ +--- +title: "JSpecify null güvenliği ile JUnit 6" +oldApproach: Açıklamasız API +modernApproach: "@NullMarked API" +summary: "JUnit 6, JSpecify @NullMarked'ı benimseyerek null sözleşmelerini doğrulama API'si genelinde açık hale getirir." +explanation: "JUnit 5, standartlaştırılmış null olabilirlik açıklamaları olmadan geldi; bu durum geliştiricilerin doğrulama parametrelerinin veya dönüş değerlerinin null olup olmayacağını tahmin etmesine neden oldu. JUnit 6, tüm modülü genelinde JSpecify'ı benimser: @NullMarked açıklaması varsayılan olarak tüm açıklamasız türleri null olmayan yapar ve @Nullable istisnaları işaretler. Assertions sınıfı, assertNull(@Nullable Object actual) ve fail(@Nullable String message) gibi parametreleri açıkça açıklar; böylece IDE'ler ve NullAway ile Error Prone gibi statik analizörler çalışma zamanı yerine derleme zamanında null kötüye kullanımını yakalayabilir." +whyModernWins: +- icon: "📜" + title: Açık sözleşmeler + desc: "JUnit 6 modülündeki @NullMarked, null anlambilimini doğrudan API'de belgeler — kaynak okumaya gerek kalmaz." +- icon: "🛡️" + title: Derleme zamanı güvenliği + desc: "IDE'ler ve analizörler, null olmayan beklenirken null geçildiğinde uyarır; testler çalıştırılmadan önce hatalar yakalanır." +- icon: "🌐" + title: Ekosistem standardı + desc: "JSpecify, Spring, Guava ve diğerleri tarafından benimsendi — tüm yığınınızda tutarlı null anlambilimi." +support: + description: "JUnit 6.0'dan itibaren kullanılabilir (Ekim 2025, Java 17+ gerektirir)" diff --git a/translations/content/tr/tooling/multi-file-source.yaml b/translations/content/tr/tooling/multi-file-source.yaml new file mode 100644 index 0000000..ea4ac91 --- /dev/null +++ b/translations/content/tr/tooling/multi-file-source.yaml @@ -0,0 +1,18 @@ +--- +title: Çok dosyalı kaynak başlatıcı +oldApproach: Önce Hepsini Derle +modernApproach: Kaynak Başlatıcı +summary: "Açık derleme adımı olmadan çok dosyalı programları başlatın." +explanation: "Java 22+, .java dosyasından başlatıldığında başvurulan kaynak dosyaları otomatik olarak derleyebilir. Bu durum, Maven veya Gradle gerektirmeden küçük çok dosyalı programların betikler kadar kolay çalıştırılmasını sağlar." +whyModernWins: +- icon: "🚀" + title: Sıfır kurulum + desc: "Küçük çok dosyalı programlar için derleme aracı gerekmez." +- icon: "🔗" + title: Otomatik çözümleme + desc: "Başvurulan sınıflar otomatik olarak bulunur ve derlenir." +- icon: "📝" + title: Betik benzeri + desc: "Çok dosyalı programları betikler gibi çalıştırın." +support: + description: "JDK 22'den itibaren kullanılabilir (Mart 2024)" diff --git a/translations/content/tr/tooling/single-file-execution.yaml b/translations/content/tr/tooling/single-file-execution.yaml new file mode 100644 index 0000000..5d6f702 --- /dev/null +++ b/translations/content/tr/tooling/single-file-execution.yaml @@ -0,0 +1,18 @@ +--- +title: Tek dosya çalıştırma +oldApproach: İki Adımlı Derleme +modernApproach: Doğrudan Başlatma +summary: "Tek dosyalı Java programlarını javac olmadan doğrudan çalıştırın." +explanation: "Java başlatıcısı, tek bir kaynak dosyayı tek komutla derleyip çalıştırabilir. Unix'te shebang desteğiyle Java dosyaları betik olarak çalışabilir. Ayrı bir derleme adımına gerek kalmaz." +whyModernWins: +- icon: "⚡" + title: Tek komut + desc: "java File.java tek adımda derler ve çalıştırır." +- icon: "📝" + title: Betik benzeri + desc: ".java dosyalarını çalıştırılabilir betik yapmak için shebang satırı ekleyin." +- icon: "🎓" + title: Öğrenmeye uygun + desc: "Yeni başlayanlar, derleme araçlarını öğrenmeden kodu hemen çalıştırabilir." +support: + description: "JDK 11'den itibaren geniş çapta kullanılabilir (Eylül 2018)" From 6a6ddde52c8698a7ce4d283d1a9879139b50538c Mon Sep 17 00:00:00 2001 From: Bruno Borges Date: Fri, 27 Feb 2026 10:56:52 -0500 Subject: [PATCH 24/28] Rewrite generate.py to match generate.java with full i18n support Bring generate.py up to parity with generate.java (the source of truth). Previously the Python script only produced English output and was missing many features added to the Java generator. Added: - Full multi-locale build support (--locale, --all-locales flags) - UI string loading from translations/strings/ with English fallback - Content translation merging (resolveSnippet) from translations/content/ - Dotted-key token regex (e.g. {{nav.allPatterns}}) - Multi-pass token replacement (3 passes for nested tokens) - Locale picker, hreflang links, and i18n script block rendering - Contribute issue URLs (code, translation, suggest) - Locale-aware URLs in nav arrows, related cards, and index cards - i18n-aware difficultyDisplay and supportBadge lookups - Locales loaded from html-generators/locales.properties Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- html-generators/generate.py | 737 +++++++++++++++++++++++++++--------- 1 file changed, 558 insertions(+), 179 deletions(-) diff --git a/html-generators/generate.py b/html-generators/generate.py index 1cef9ea..0c7ea77 100644 --- a/html-generators/generate.py +++ b/html-generators/generate.py @@ -1,173 +1,305 @@ #!/usr/bin/env python3 -"""Generate HTML detail pages from JSON snippet files and slug-template.html.""" +""" +Generate HTML detail pages from JSON snippet files and slug-template.html. +Python equivalent of generate.java — produces identical output. +""" +import argparse +import copy import json import yaml import glob import os -import html +import html as html_mod import re +from collections import OrderedDict from urllib.parse import quote BASE_URL = "https://javaevolved.github.io" -TEMPLATE_FILE = "templates/slug-template.html" -WHY_CARD_TEMPLATE = "templates/why-card.html" -RELATED_CARD_TEMPLATE = "templates/related-card.html" -SOCIAL_SHARE_TEMPLATE = "templates/social-share.html" -DOC_LINK_TEMPLATE = "templates/doc-link.html" -INDEX_TEMPLATE = "templates/index.html" -INDEX_CARD_TEMPLATE = "templates/index-card.html" CONTENT_DIR = "content" SITE_DIR = "site" - +TRANSLATIONS_DIR = "translations" CATEGORIES_FILE = "html-generators/categories.properties" +LOCALES_FILE = "html-generators/locales.properties" +GITHUB_ISSUES_URL = "https://github.com/javaevolved/javaevolved.github.io/issues/new" + +TOKEN_RE = re.compile(r"\{\{([\w.]+)\}\}") + +EXCLUDED_KEYS = {"_path", "prev", "next", "related"} + +TRANSLATABLE_FIELDS = { + "title", "summary", "explanation", "oldApproach", "modernApproach", + "whyModernWins", "support", +} -def load_category_display(): - """Load category display names from the properties file.""" - categories = {} - with open(CATEGORIES_FILE) as f: +# --------------------------------------------------------------------------- +# Properties / config loaders +# --------------------------------------------------------------------------- + +def _load_properties(path): + """Load a .properties file into an OrderedDict, preserving insertion order.""" + props = OrderedDict() + with open(path) as f: for line in f: line = line.strip() - if not line or line.startswith('#'): + if not line or line.startswith("#"): continue - key, sep, value = line.partition('=') - key, value = key.strip(), value.strip() - if sep and key: - categories[key] = value - return categories + idx = line.find("=") + if idx > 0: + props[line[:idx].strip()] = line[idx + 1:].strip() + return props -CATEGORY_DISPLAY = load_category_display() +CATEGORY_DISPLAY = _load_properties(CATEGORIES_FILE) +LOCALES = _load_properties(LOCALES_FILE) -def escape(text): - """HTML-escape text for use in attributes and content.""" - return html.escape(text, quote=True) +# --------------------------------------------------------------------------- +# File helpers (multi-format: .json, .yaml, .yml) +# --------------------------------------------------------------------------- +def _find_with_extensions(directory, base_name): + """Return the first existing file matching base_name.{json,yaml,yml} in directory.""" + for ext in ("json", "yaml", "yml"): + p = os.path.join(directory, f"{base_name}.{ext}") + if os.path.isfile(p): + return p + return None -def replace_tokens(template, replacements): - """Replace {{token}} placeholders in a template string.""" - def replacer(m): - key = m.group(1) - return replacements.get(key, m.group(0)) - return re.sub(r"\{\{(\w+)\}\}", replacer, template) + +def _read_auto(path): + """Read a JSON or YAML file based on its extension.""" + with open(path) as f: + if path.endswith(".yaml") or path.endswith(".yml"): + return yaml.safe_load(f) + return json.load(f) + + +# --------------------------------------------------------------------------- +# UI strings (i18n) +# --------------------------------------------------------------------------- + +def _flatten(obj, prefix=""): + """Flatten a nested dict into dot-separated keys.""" + flat = {} + for k, v in obj.items(): + key = f"{prefix}.{k}" if prefix else k + if isinstance(v, dict): + flat.update(_flatten(v, key)) + else: + flat[key] = str(v) + return flat + + +def load_strings(locale): + """Load UI strings for a locale with English fallback for missing keys.""" + en_path = _find_with_extensions(os.path.join(TRANSLATIONS_DIR, "strings"), "en") + if not en_path: + raise FileNotFoundError("No English strings file found") + en_strings = _flatten(_read_auto(en_path)) + + if locale == "en": + return en_strings + + locale_path = _find_with_extensions(os.path.join(TRANSLATIONS_DIR, "strings"), locale) + if not locale_path: + print(f"[WARN] strings/{locale}.{{json,yaml,yml}} not found — using all English strings") + return dict(en_strings) + + locale_strings = _flatten(_read_auto(locale_path)) + merged = dict(en_strings) + for key, value in locale_strings.items(): + if key in en_strings: + merged[key] = value + # Warn about missing keys + locale_file = os.path.basename(locale_path) + for key in en_strings: + if key not in locale_strings: + print(f'[WARN] {locale_file}: missing key "{key}" — using English fallback') + return merged + + +# --------------------------------------------------------------------------- +# Snippet helpers +# --------------------------------------------------------------------------- + +def _get(data, field): + return data[field] + + +def _opt(data, field): + v = data.get(field) + return v if v is not None else None + + +def _key(data): + return f"{data['category']}/{data['slug']}" + + +def _cat_display(data): + return CATEGORY_DISPLAY[data["category"]] + + +# --------------------------------------------------------------------------- +# Escape helpers +# --------------------------------------------------------------------------- + +def escape(text): + """HTML-escape text for use in attributes and content.""" + if text is None: + return "" + return html_mod.escape(str(text), quote=True) def json_escape(text): """Escape text for embedding in JSON strings inside ld+json blocks. - - Uses ASCII-only encoding to match the original HTML files which use - \\uXXXX escapes for non-ASCII characters in ld+json blocks. + Uses ASCII-only encoding with \\uXXXX escapes for non-ASCII characters. """ return json.dumps(text, ensure_ascii=True)[1:-1] -def load_template(): - """Load the external HTML template.""" - with open(TEMPLATE_FILE) as f: - return f.read() +def js_escape(s): + """Escape a string for embedding inside a JS double-quoted string.""" + return s.replace("\\", "\\\\").replace('"', '\\"').replace("\n", "\\n") +def url_encode(s): + return quote(s, safe="") + + +# --------------------------------------------------------------------------- +# Token replacement (multi-pass, supports dotted keys) +# --------------------------------------------------------------------------- + +def replace_tokens(template, replacements): + """Replace {{token}} placeholders; up to 3 passes for nested tokens.""" + result = template + for _ in range(3): + found = False + def replacer(m): + nonlocal found + key = m.group(1) + val = replacements.get(key) + if val is not None: + found = True + return val + return m.group(0) + result = TOKEN_RE.sub(replacer, result) + if not found: + break + return result + + +# --------------------------------------------------------------------------- +# Load all English snippets +# --------------------------------------------------------------------------- + def load_all_snippets(): - """Load all JSON snippet files, keyed by category/slug.""" - snippets = {} - json_files = [] + """Load all content snippet files, keyed by category/slug, in sorted order.""" + snippets = OrderedDict() for cat in CATEGORY_DISPLAY: - json_files.extend(glob.glob(f"{CONTENT_DIR}/{cat}/*.json")) - json_files.extend(glob.glob(f"{CONTENT_DIR}/{cat}/*.yaml")) - json_files.extend(glob.glob(f"{CONTENT_DIR}/{cat}/*.yml")) - json_files.sort() - for path in json_files: - with open(path) as f: - if path.endswith(".yaml") or path.endswith(".yml"): - data = yaml.safe_load(f) - else: - data = json.load(f) - key = f"{data['category']}/{data['slug']}" - data["_path"] = key - snippets[key] = data + cat_dir = os.path.join(CONTENT_DIR, cat) + if not os.path.isdir(cat_dir): + continue + files = [] + for ext in ("json", "yaml", "yml"): + files.extend(glob.glob(os.path.join(cat_dir, f"*.{ext}"))) + files.sort() + for path in files: + data = _read_auto(path) + data["_path"] = _key(data) + snippets[_key(data)] = data return snippets -def render_nav_arrows(data): - """Render prev/next navigation arrows.""" - parts = [] - if data.get("prev"): - parts.append( - f'' - ) - else: - parts.append('') - if data.get("next"): - parts.append( - f'' - ) - else: - parts.append("") - return "\n ".join(parts) +# --------------------------------------------------------------------------- +# Translation merging +# --------------------------------------------------------------------------- + +def resolve_snippet(english_snippet, locale): + """Overlay translated content onto the English base for a given locale.""" + if locale == "en": + return english_snippet + + translated_dir = os.path.join(TRANSLATIONS_DIR, "content", locale, english_snippet["category"]) + translated_path = _find_with_extensions(translated_dir, english_snippet["slug"]) + if not translated_path: + return english_snippet + + try: + translated = _read_auto(translated_path) + merged = copy.deepcopy(english_snippet) + for field in TRANSLATABLE_FIELDS: + if field in translated: + if field == "support" and isinstance(translated["support"], dict): + if "description" in translated["support"]: + merged["support"]["description"] = translated["support"]["description"] + else: + merged[field] = translated[field] + return merged + except Exception: + print(f"[WARN] Failed to load {translated_path} — using English") + return english_snippet + + +# --------------------------------------------------------------------------- +# Badge / display helpers +# --------------------------------------------------------------------------- + +def support_badge(state, strings): + return { + "preview": strings.get("support.preview", "Preview"), + "experimental": strings.get("support.experimental", "Experimental"), + }.get(state, strings.get("support.available", "Available")) + + +def support_badge_class(state): + return {"preview": "preview", "experimental": "experimental"}.get(state, "widely") -def render_why_cards(why_card_template, why_list): - """Render the 3 why-modern-wins cards.""" - cards = [] - for w in why_list: - cards.append( - replace_tokens(why_card_template, { - "icon": w["icon"], - "title": escape(w["title"]), - "desc": escape(w["desc"]), - }) - ) - return "\n".join(cards) +def difficulty_display(difficulty, strings): + return strings.get(f"difficulty.{difficulty}", difficulty) -def render_related_card(related_card_template, related_data): - """Render a single related pattern tip-card.""" - cat = related_data["category"] - cat_display = CATEGORY_DISPLAY[cat] +# --------------------------------------------------------------------------- +# Render helpers +# --------------------------------------------------------------------------- - return replace_tokens(related_card_template, { - "category": cat, - "slug": related_data["slug"], - "catDisplay": cat_display, - "difficulty": related_data["difficulty"], - "title": escape(related_data["title"]), - "oldLabel": escape(related_data["oldLabel"]), - "oldCode": escape(related_data["oldCode"]), - "modernLabel": escape(related_data["modernLabel"]), - "modernCode": escape(related_data["modernCode"]), - "jdkVersion": related_data["jdkVersion"], - }) +def render_nav_arrows(data, locale): + """Render prev/next navigation arrows with locale-aware paths.""" + prefix = "" if locale == "en" else f"/{locale}" + prev_val = _opt(data, "prev") + next_val = _opt(data, "next") + prev_html = ( + f'' + if prev_val + else '' + ) + next_html = ( + f'' + if next_val + else "" + ) + return prev_html + "\n " + next_html -def render_related_section(related_card_template, related_paths, all_snippets): - """Render all related pattern cards.""" +def render_why_cards(tpl, why_list): + """Render the 3 why-modern-wins cards.""" cards = [] - for path in related_paths: - if path in all_snippets: - cards.append(render_related_card(related_card_template, all_snippets[path])) + for w in why_list: + cards.append(replace_tokens(tpl, { + "icon": w["icon"], + "title": escape(w["title"]), + "desc": escape(w["desc"]), + })) return "\n".join(cards) -def render_social_share(social_share_template, slug, title): - """Render social share URLs using the old flat URL format.""" - page_url = f"{BASE_URL}/{slug}.html" - share_text = f"{title} \u2013 java.evolved" - - encoded_url = quote(page_url, safe="") - encoded_text = quote(share_text, safe="") - - return replace_tokens(social_share_template, { - "encodedUrl": encoded_url, - "encodedText": encoded_text, - }) - - -def render_doc_links(doc_link_template, docs): +def render_doc_links(tpl, docs): """Render documentation links.""" return "\n".join( - replace_tokens(doc_link_template, { + replace_tokens(tpl, { "docTitle": escape(d["title"]), "docHref": d["href"], }) @@ -175,43 +307,200 @@ def render_doc_links(doc_link_template, docs): ) -def _support_badge(state): - return {"preview": "Preview", "experimental": "Experimental"}.get(state, "Available") +def render_related_card(tpl, rel, locale, strings): + """Render a single related pattern tip-card.""" + related_href = ( + f"/{rel['category']}/{rel['slug']}.html" + if locale == "en" + else f"/{locale}/{rel['category']}/{rel['slug']}.html" + ) + return replace_tokens(tpl, { + "category": rel["category"], + "slug": rel["slug"], + "catDisplay": _cat_display(rel), + "difficulty": rel["difficulty"], + "difficultyDisplay": difficulty_display(rel["difficulty"], strings), + "title": escape(rel["title"]), + "oldLabel": escape(rel["oldLabel"]), + "oldCode": escape(rel["oldCode"]), + "modernLabel": escape(rel["modernLabel"]), + "modernCode": escape(rel["modernCode"]), + "jdkVersion": rel["jdkVersion"], + "relatedHref": related_href, + "cards.hoverHintRelated": strings.get("cards.hoverHintRelated", "Hover to see modern ➜"), + }) + + +def render_related_section(tpl, data, all_snippets, locale, strings): + """Render all related pattern cards.""" + related = data.get("related", []) + cards = [] + for path in related: + if path in all_snippets: + cards.append(render_related_card(tpl, all_snippets[path], locale, strings)) + return "\n".join(cards) -def _support_badge_class(state): - return {"preview": "preview", "experimental": "experimental"}.get(state, "widely") +def render_social_share(tpl, slug, title, strings): + """Render social share URLs.""" + encoded_url = url_encode(f"{BASE_URL}/{slug}.html") + encoded_text = url_encode(f"{title} \u2013 java.evolved") + return replace_tokens(tpl, { + "encodedUrl": encoded_url, + "encodedText": encoded_text, + "share.label": strings.get("share.label", "Share"), + }) -def render_index_card(index_card_template, data): +def render_index_card(tpl, data, locale, strings): """Render a single index page preview card.""" - cat = data["category"] - return replace_tokens(index_card_template, { - "category": cat, + card_href = ( + f"/{data['category']}/{data['slug']}.html" + if locale == "en" + else f"/{locale}/{data['category']}/{data['slug']}.html" + ) + return replace_tokens(tpl, { + "category": data["category"], "slug": data["slug"], - "catDisplay": CATEGORY_DISPLAY[cat], + "catDisplay": _cat_display(data), "title": escape(data["title"]), "oldCode": escape(data["oldCode"]), "modernCode": escape(data["modernCode"]), "jdkVersion": data["jdkVersion"], + "cardHref": card_href, + "cards.old": strings.get("cards.old", "Old"), + "cards.modern": strings.get("cards.modern", "Modern"), + "cards.hoverHint": strings.get("cards.hoverHint", "hover to see modern →"), + "cards.learnMore": strings.get("cards.learnMore", "learn more"), }) -def generate_html(template, why_card_template, related_card_template, - social_share_template, doc_link_template, data, all_snippets): +# --------------------------------------------------------------------------- +# Locale picker, hreflang, i18n script +# --------------------------------------------------------------------------- + +def render_locale_picker(current_locale): + """Render the locale picker dropdown HTML.""" + lines = [] + lines.append('

') + lines.append(' ') + lines.append('
    ') + for loc, name in LOCALES.items(): + selected = loc == current_locale + cls = ' class="active"' if selected else "" + lines.append(f'
  • {name}
  • ') + lines.append("
") + lines.append("
") + return "\n".join(lines) + + +def render_hreflang_links(path_part, slug): + """Render hreflang tags for all locales.""" + lines = [] + for loc in LOCALES: + if slug == "index": + href = f"{BASE_URL}/" if loc == "en" else f"{BASE_URL}/{loc}/" + else: + href = ( + f"{BASE_URL}/{path_part}{slug}.html" + if loc == "en" + else f"{BASE_URL}/{loc}/{path_part}{slug}.html" + ) + lines.append(f' ') + # x-default points to English + default_href = ( + f"{BASE_URL}/" if slug == "index" + else f"{BASE_URL}/{path_part}{slug}.html" + ) + lines.append(f' ') + return "\n".join(lines) + + +def render_i18n_script(strings, locale): + """Render the i18n script block for client-side JS.""" + locale_array = ", ".join(f'"{loc}"' for loc in LOCALES) + return ( + "" + ) + + +# --------------------------------------------------------------------------- +# Contribute URLs +# --------------------------------------------------------------------------- + +def build_contribute_urls(data, locale, locale_name): + """Build GitHub issue template URLs for contribute links.""" + title = data["title"] + category = data["category"] + slug = data["slug"] + + code_url = ( + f"{GITHUB_ISSUES_URL}?template=code-issue.yml" + f"&title={url_encode(f'[Code Issue] {title}')}" + f"&category={url_encode(category)}" + f"&slug={url_encode(slug)}" + ) + + clean_locale_name = re.sub(r"^[^\w]", "", locale_name, flags=re.UNICODE) + # Strip leading non-letter chars (match Java's ^[^\p{L}]+) + clean_locale_name = re.sub(r"^[^a-zA-Z\u00C0-\u024F\u0400-\u04FF\u0600-\u06FF\u3000-\u9FFF\uAC00-\uD7AF]+", "", locale_name) + + trans_url = ( + f"{GITHUB_ISSUES_URL}?template=translation-issue.yml" + f"&title={url_encode(f'[Translation] {title} ({clean_locale_name})')}" + f"&locale={url_encode(locale)}" + f"&pattern={url_encode(slug)}" + f"&area={url_encode('Pattern content')}" + ) + + suggest_url = f"{GITHUB_ISSUES_URL}?template=new-pattern.yml" + + return { + "contributeCodeIssueUrl": code_url, + "contributeTranslationIssueUrl": trans_url, + "contributeSuggestUrl": suggest_url, + } + + +# --------------------------------------------------------------------------- +# HTML generation +# --------------------------------------------------------------------------- + +def generate_html(templates, data, all_snippets, extra_tokens, locale): """Generate the full HTML page for a snippet by rendering the template.""" + is_english = locale == "en" cat = data["category"] slug = data["slug"] - cat_display = CATEGORY_DISPLAY[cat] + cat_display = _cat_display(data) + + canonical_url = ( + f"{BASE_URL}/{cat}/{slug}.html" + if is_english + else f"{BASE_URL}/{locale}/{cat}/{slug}.html" + ) - # Build the substitution map - replacements = { + tokens = dict(extra_tokens) + tokens.update({ "title": escape(data["title"]), "summary": escape(data["summary"]), "slug": slug, "category": cat, "categoryDisplay": cat_display, "difficulty": data["difficulty"], + "difficultyDisplay": difficulty_display(data["difficulty"], extra_tokens), "jdkVersion": data["jdkVersion"], "oldLabel": escape(data["oldLabel"]), "modernLabel": escape(data["modernLabel"]), @@ -221,79 +510,169 @@ def generate_html(template, why_card_template, related_card_template, "modernApproach": escape(data["modernApproach"]), "explanation": escape(data["explanation"]), "supportDescription": escape(data["support"]["description"]), - "supportBadge": _support_badge(data["support"]["state"]), - "supportBadgeClass": _support_badge_class(data["support"]["state"]), - "locale": "en", - "htmlDir": "ltr", - "canonicalUrl": f"{BASE_URL}/{cat}/{slug}.html", + "supportBadge": support_badge(data["support"]["state"], extra_tokens), + "supportBadgeClass": support_badge_class(data["support"]["state"]), + "canonicalUrl": canonical_url, "flatUrl": f"{BASE_URL}/{slug}.html", "titleJson": json_escape(data["title"]), "summaryJson": json_escape(data["summary"]), "categoryDisplayJson": json_escape(cat_display), - "navArrows": render_nav_arrows(data), - "whyCards": render_why_cards(why_card_template, data["whyModernWins"]), - "docLinks": render_doc_links(doc_link_template, data.get("docs", [])), - "relatedCards": render_related_section(related_card_template, data.get("related", []), all_snippets), - "socialShare": render_social_share(social_share_template, slug, data["title"]), - } + "navArrows": render_nav_arrows(data, locale), + "whyCards": render_why_cards(templates["why_card"], data["whyModernWins"]), + "docLinks": render_doc_links(templates["doc_link"], data.get("docs", [])), + "relatedCards": render_related_section( + templates["related_card"], data, all_snippets, locale, extra_tokens + ), + "socialShare": render_social_share( + templates["social_share"], slug, data["title"], extra_tokens + ), + }) - return replace_tokens(template, replacements) + locale_name = LOCALES.get(locale, locale) + tokens.update(build_contribute_urls(data, locale, locale_name)) + return replace_tokens(templates["page"], tokens) -def main(): - template = load_template() - why_card_template = open(WHY_CARD_TEMPLATE).read() - related_card_template = open(RELATED_CARD_TEMPLATE).read() - social_share_template = open(SOCIAL_SHARE_TEMPLATE).read() - doc_link_template = open(DOC_LINK_TEMPLATE).read() - index_template = open(INDEX_TEMPLATE).read() - index_card_template = open(INDEX_CARD_TEMPLATE).read() - all_snippets = load_all_snippets() - print(f"Loaded {len(all_snippets)} snippets") - for key, data in all_snippets.items(): - html_content = generate_html( - template, why_card_template, related_card_template, - social_share_template, doc_link_template, data, all_snippets - ).strip() - out_dir = os.path.join(SITE_DIR, data['category']) +# --------------------------------------------------------------------------- +# Build a single locale +# --------------------------------------------------------------------------- + +def build_locale(locale, templates, all_snippets): + """Build all HTML files for a single locale.""" + is_english = locale == "en" + strings = load_strings(locale) + locale_name = LOCALES.get(locale, locale) + base_prefix = "../" if is_english else "../../" + home_url = "/" if is_english else f"/{locale}/" + + print(f"Building locale: {locale} ({locale_name})") + + locale_picker_html = render_locale_picker(locale) + index_hreflang = render_hreflang_links("", "index") + i18n_script = render_i18n_script(strings, locale) + + for snippet in all_snippets.values(): + resolved = resolve_snippet(snippet, locale) + detail_hreflang = render_hreflang_links(f"{snippet['category']}/", snippet["slug"]) + + extra_tokens = dict(strings) + extra_tokens.update({ + "locale": locale, + "htmlDir": "rtl" if locale == "ar" else "ltr", + "ogLocale": locale.replace("-", "_"), + "basePrefix": base_prefix, + "homeUrl": home_url, + "localePicker": locale_picker_html, + "hreflangLinks": detail_hreflang, + "i18nScript": i18n_script, + }) + + html_content = generate_html(templates, resolved, all_snippets, extra_tokens, locale).strip() + + if is_english: + out_dir = os.path.join(SITE_DIR, snippet["category"]) + else: + out_dir = os.path.join(SITE_DIR, locale, snippet["category"]) os.makedirs(out_dir, exist_ok=True) - out_path = os.path.join(out_dir, f"{data['slug']}.html") + out_path = os.path.join(out_dir, f"{snippet['slug']}.html") with open(out_path, "w", newline="") as f: f.write(html_content) - print(f"Generated {len(all_snippets)} HTML files") + print(f"Generated {len(all_snippets)} HTML files for {locale}") - # Rebuild data/snippets.json from individual JSON files - # This file is used at runtime by app.js for search + # Rebuild data/snippets.json snippets_list = [] - for key, data in all_snippets.items(): - entry = {k: v for k, v in data.items() if k not in ("_path", "prev", "next", "related")} + for s in all_snippets.values(): + resolved = resolve_snippet(s, locale) + entry = {k: v for k, v in resolved.items() if k not in EXCLUDED_KEYS} snippets_list.append(entry) - os.makedirs(os.path.join(SITE_DIR, "data"), exist_ok=True) - with open(os.path.join(SITE_DIR, "data", "snippets.json"), "w") as f: + data_dir = ( + os.path.join(SITE_DIR, "data") + if is_english + else os.path.join(SITE_DIR, locale, "data") + ) + os.makedirs(data_dir, exist_ok=True) + with open(os.path.join(data_dir, "snippets.json"), "w") as f: json.dump(snippets_list, f, indent=2, ensure_ascii=False) f.write("\n") - - print(f"Rebuilt data/snippets.json with {len(snippets_list)} entries") + print(f"Rebuilt data/snippets.json for {locale} with {len(snippets_list)} entries") # Generate index.html from template tip_cards = "\n".join( - render_index_card(index_card_template, data) - for data in all_snippets.values() + render_index_card(templates["index_card"], resolve_snippet(s, locale), locale, strings) + for s in all_snippets.values() ) - count = len(all_snippets) - index_html = replace_tokens(index_template, { + + index_tokens = dict(strings) + index_tokens.update({ "tipCards": tip_cards, - "snippetCount": str(count), - "locale": "en", - "htmlDir": "ltr", + "snippetCount": str(len(all_snippets)), + "locale": locale, + "htmlDir": "rtl" if locale == "ar" else "ltr", + "ogLocale": locale.replace("-", "_"), + "canonicalUrl": BASE_URL if is_english else f"{BASE_URL}/{locale}", + "homeUrl": home_url, + "indexBasePrefix": "" if is_english else "../", + "localePicker": locale_picker_html, + "hreflangLinks": index_hreflang, + "i18nScript": i18n_script, }) - with open(os.path.join(SITE_DIR, "index.html"), "w") as f: + + index_html = replace_tokens(templates["index"], index_tokens) + if is_english: + index_path = os.path.join(SITE_DIR, "index.html") + else: + index_dir = os.path.join(SITE_DIR, locale) + os.makedirs(index_dir, exist_ok=True) + index_path = os.path.join(index_dir, "index.html") + with open(index_path, "w") as f: f.write(index_html) + print(f"Generated index.html for {locale} with {len(all_snippets)} cards") + + +# --------------------------------------------------------------------------- +# Templates loader +# --------------------------------------------------------------------------- + +def load_templates(): + """Load all HTML templates.""" + def _read(path): + with open(path) as f: + return f.read() + return { + "page": _read("templates/slug-template.html"), + "why_card": _read("templates/why-card.html"), + "related_card": _read("templates/related-card.html"), + "social_share": _read("templates/social-share.html"), + "index": _read("templates/index.html"), + "index_card": _read("templates/index-card.html"), + "doc_link": _read("templates/doc-link.html"), + } + + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- + +def main(): + parser = argparse.ArgumentParser(description="Generate java.evolved site HTML") + parser.add_argument("--all-locales", action="store_true", help="Build all locales") + parser.add_argument("--locale", type=str, help="Build a single locale") + args = parser.parse_args() + + templates = load_templates() + all_snippets = load_all_snippets() + print(f"Loaded {len(all_snippets)} snippets") + + if args.locale: + locales_to_build = [args.locale] + else: + locales_to_build = list(LOCALES.keys()) - print(f"Generated index.html with {count} cards") + for locale in locales_to_build: + build_locale(locale, templates, all_snippets) if __name__ == "__main__": From 6d0fa87971f4c3925922eeda9fbe8c4b88409531 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 22:57:44 +0000 Subject: [PATCH 25/28] Initial plan From fc867863f50ddc01fa2051610a1631a800fbf87a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 23:21:26 +0000 Subject: [PATCH 26/28] Add automated proof script for code snippet verification - Add html-generators/proof.java: JBang script (Java 25) that reads all content YAML files, finds those with an optional proofCode field, and runs each through JShell to verify they compile and execute correctly. Supports --list flag to show which patterns have/lack proofCode. - Add .github/workflows/proof.yml: GitHub Actions workflow that triggers on content changes (push/PR) and runs jbang html-generators/proof.java with Java 25 + JBang. - Add proofCode field to 10 representative patterns across categories: language (var, text-blocks, records, switch, instanceof), collections (immutable-list), streams (stream-tolist), strings (isBlank), concurrency (virtual-threads), datetime (java-time-basics) - Update generate.java and generate.py to exclude proofCode from the search index (snippets.json) since it is CI-only metadata. - Update content/template.json, html-generators/README.md, CONTRIBUTING.md, and copilot-instructions.md to document the new field. Co-authored-by: brunoborges <129743+brunoborges@users.noreply.github.com> --- .github/copilot-instructions.md | 4 +- .github/workflows/proof.yml | 33 ++++ CONTRIBUTING.md | 3 +- .../collections/immutable-list-creation.yaml | 8 + content/concurrency/virtual-threads.yaml | 10 ++ content/datetime/java-time-basics.yaml | 9 + .../language/pattern-matching-instanceof.yaml | 8 + .../language/records-for-data-classes.yaml | 5 + content/language/switch-expressions.yaml | 9 + .../text-blocks-for-multiline-strings.yaml | 9 + content/language/type-inference-with-var.yaml | 7 + content/streams/stream-tolist.yaml | 4 + content/strings/string-isblank.yaml | 5 + content/template.json | 3 +- html-generators/README.md | 5 +- html-generators/generate.java | 2 +- html-generators/generate.py | 2 +- html-generators/proof.java | 167 ++++++++++++++++++ 18 files changed, 287 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/proof.yml create mode 100644 html-generators/proof.java diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index c637dce..9244879 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -100,7 +100,8 @@ Each `content/category/slug.json` file has this structure: ], "docs": [ { "title": "Javadoc or Guide Title", "href": "https://docs.oracle.com/..." } - ] + ], + "proofCode": "// Optional: self-contained JShell snippet proving the modern approach works.\n// Run with: jbang html-generators/proof.java" } ``` @@ -113,6 +114,7 @@ Each `content/category/slug.json` file has this structure: - `docs` must have at least **1** entry linking to Javadoc or Oracle documentation - `prev`/`next` are `category/slug` paths or `null` for first/last - Code in `oldCode`/`modernCode` uses `\n` for newlines +- `proofCode` is optional — a self-contained JShell snippet (with default imports available) that proves the modern approach compiles and runs correctly. Run `jbang html-generators/proof.java` to verify all proof snippets. ## Category Display Names diff --git a/.github/workflows/proof.yml b/.github/workflows/proof.yml new file mode 100644 index 0000000..46204f9 --- /dev/null +++ b/.github/workflows/proof.yml @@ -0,0 +1,33 @@ +name: Proof + +on: + push: + branches: [main] + paths: + - 'content/**' + - 'html-generators/proof.java' + - '.github/workflows/proof.yml' + pull_request: + paths: + - 'content/**' + - 'html-generators/proof.java' + workflow_dispatch: + +permissions: + contents: read + +jobs: + proof: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '25' + + - uses: jbangdev/setup-jbang@main + + - name: Run proof + run: jbang html-generators/proof.java diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5fa0318..48e7fc1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,8 @@ Contributions are welcome! Content is managed as YAML files — never edit gener 3. Copy [`content/template.json`](content/template.json) as a starting point for all required fields (see the [snippet schema](.github/copilot-instructions.md) for details) 4. Update the `prev`/`next` fields in adjacent pattern files to maintain navigation 5. Run `jbang html-generators/generate.java` to verify your changes build correctly -6. Open a pull request +6. Optionally add a `proofCode` field — a self-contained JShell snippet that proves the modern approach works. Run `jbang html-generators/proof.java` to validate it. +7. Open a pull request Please ensure JDK version labels only reference the version where a feature became **final** (non-preview). diff --git a/content/collections/immutable-list-creation.yaml b/content/collections/immutable-list-creation.yaml index 0b33dca..c49094d 100644 --- a/content/collections/immutable-list-creation.yaml +++ b/content/collections/immutable-list-creation.yaml @@ -47,3 +47,11 @@ docs: href: "https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/List.html#of()" - title: "Collections Factory Methods (JEP 269)" href: "https://openjdk.org/jeps/269" +proofCode: |- + var list = List.of("a", "b", "c"); + if (list.size() != 3) throw new AssertionError("expected 3 elements"); + try { + list.add("d"); + throw new AssertionError("should have thrown UnsupportedOperationException"); + } catch (UnsupportedOperationException ok) {} + IO.println("immutable list: OK - " + list); diff --git a/content/concurrency/virtual-threads.yaml b/content/concurrency/virtual-threads.yaml index 3e5e6ab..0970c44 100644 --- a/content/concurrency/virtual-threads.yaml +++ b/content/concurrency/virtual-threads.yaml @@ -47,3 +47,13 @@ docs: href: "https://openjdk.org/jeps/444" - title: "Thread.ofVirtual()" href: "https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/Thread.html#ofVirtual()" +proofCode: |- + var results = new java.util.concurrent.CopyOnWriteArrayList(); + var threads = new ArrayList(); + for (int i = 0; i < 5; i++) { + int idx = i; + threads.add(Thread.startVirtualThread(() -> results.add("vt-" + idx))); + } + for (var t : threads) t.join(); + if (results.size() != 5) throw new AssertionError("expected 5 results, got: " + results.size()); + IO.println("virtual threads: OK - " + results.size() + " threads ran"); diff --git a/content/datetime/java-time-basics.yaml b/content/datetime/java-time-basics.yaml index 0b11f4d..cdc29c9 100644 --- a/content/datetime/java-time-basics.yaml +++ b/content/datetime/java-time-basics.yaml @@ -51,3 +51,12 @@ docs: href: "https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/time/LocalTime.html" - title: "LocalDateTime" href: "https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/time/LocalDateTime.html" +proofCode: |- + import java.time.*; + var date = LocalDate.of(2025, Month.JANUARY, 15); + var time = LocalTime.of(14, 30); + if (date.getMonthValue() != 1) throw new AssertionError("expected January=1, got: " + date.getMonthValue()); + if (time.getHour() != 14) throw new AssertionError("expected hour=14, got: " + time.getHour()); + var now = Instant.now(); + if (now == null) throw new AssertionError("Instant.now() returned null"); + IO.println("java.time basics: OK - " + date + " " + time); diff --git a/content/language/pattern-matching-instanceof.yaml b/content/language/pattern-matching-instanceof.yaml index d4306b7..9318d87 100644 --- a/content/language/pattern-matching-instanceof.yaml +++ b/content/language/pattern-matching-instanceof.yaml @@ -44,3 +44,11 @@ related: docs: - title: "Pattern Matching for instanceof (JEP 394)" href: "https://openjdk.org/jeps/394" +proofCode: |- + Object obj = "Hello, pattern matching!"; + if (obj instanceof String s) { + IO.println("length=" + s.length()); + } else { + throw new AssertionError("should have matched String"); + } + IO.println("pattern matching instanceof: OK"); diff --git a/content/language/records-for-data-classes.yaml b/content/language/records-for-data-classes.yaml index bcc1bc0..ee9e661 100644 --- a/content/language/records-for-data-classes.yaml +++ b/content/language/records-for-data-classes.yaml @@ -46,3 +46,8 @@ docs: href: "https://openjdk.org/jeps/395" - title: "Record class" href: "https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/Record.html" +proofCode: |- + public record Point(int x, int y) {} + var p = new Point(1, 2); + if (p.x() != 1 || p.y() != 2) throw new AssertionError("accessor mismatch"); + IO.println("records: OK - " + p); diff --git a/content/language/switch-expressions.yaml b/content/language/switch-expressions.yaml index 5e099c4..0726089 100644 --- a/content/language/switch-expressions.yaml +++ b/content/language/switch-expressions.yaml @@ -53,3 +53,12 @@ related: docs: - title: "Switch Expressions (JEP 361)" href: "https://openjdk.org/jeps/361" +proofCode: |- + var day = "MONDAY"; + String msg = switch (day) { + case "MONDAY" -> "Start"; + case "FRIDAY" -> "End"; + default -> "Mid"; + }; + if (!"Start".equals(msg)) throw new AssertionError("unexpected: " + msg); + IO.println("switch expressions: OK - " + msg); diff --git a/content/language/text-blocks-for-multiline-strings.yaml b/content/language/text-blocks-for-multiline-strings.yaml index dd358c0..8bce5e6 100644 --- a/content/language/text-blocks-for-multiline-strings.yaml +++ b/content/language/text-blocks-for-multiline-strings.yaml @@ -49,3 +49,12 @@ docs: href: "https://openjdk.org/jeps/378" - title: "Text Blocks Guide" href: "https://docs.oracle.com/en/java/javase/25/language/text-blocks.html" +proofCode: |- + String json = """ + { + "name": "Duke", + "age": 30 + }"""; + if (!json.contains("Duke")) throw new AssertionError("text block content missing"); + if (json.contains("\\n")) throw new AssertionError("should not contain literal \\n"); + IO.println("text blocks: OK"); diff --git a/content/language/type-inference-with-var.yaml b/content/language/type-inference-with-var.yaml index 4eba7d4..8bc5be4 100644 --- a/content/language/type-inference-with-var.yaml +++ b/content/language/type-inference-with-var.yaml @@ -49,3 +49,10 @@ docs: href: "https://openjdk.org/jeps/286" - title: "Style Guidelines for var" href: "https://openjdk.org/projects/amber/guides/lvti-style-guide" +proofCode: |- + var map = new HashMap>(); + map.put("a", List.of(1, 2, 3)); + for (var entry : map.entrySet()) { + IO.println("key=" + entry.getKey() + " value=" + entry.getValue()); + } + IO.println("var: OK"); diff --git a/content/streams/stream-tolist.yaml b/content/streams/stream-tolist.yaml index 5536c3a..0d4ef2b 100644 --- a/content/streams/stream-tolist.yaml +++ b/content/streams/stream-tolist.yaml @@ -42,3 +42,7 @@ related: docs: - title: "Stream.toList()" href: "https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/stream/Stream.html#toList()" +proofCode: |- + var result = Stream.of("hello", "world", "java", "go").filter(s -> s.length() > 3).toList(); + if (result.size() != 3) throw new AssertionError("expected 3 elements, got: " + result); + IO.println("stream.toList(): OK - " + result); diff --git a/content/strings/string-isblank.yaml b/content/strings/string-isblank.yaml index 7969721..b656b83 100644 --- a/content/strings/string-isblank.yaml +++ b/content/strings/string-isblank.yaml @@ -41,3 +41,8 @@ related: docs: - title: "String.isBlank()" href: "https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/String.html#isBlank()" +proofCode: |- + if (!" ".isBlank()) throw new AssertionError("spaces should be blank"); + if (!"".isBlank()) throw new AssertionError("empty string should be blank"); + if ("hello".isBlank()) throw new AssertionError("non-empty string should not be blank"); + IO.println("String.isBlank(): OK"); diff --git a/content/template.json b/content/template.json index 8a7da6d..504a407 100644 --- a/content/template.json +++ b/content/template.json @@ -46,5 +46,6 @@ "title": "Javadoc or Guide Title", "href": "https://docs.oracle.com/..." } - ] + ], + "proofCode": "// Optional: a self-contained JShell snippet that proves the modern approach works.\n// Run all proofCode snippets with: jbang html-generators/proof.java\n// Example: var list = List.of(\"a\", \"b\", \"c\"); IO.println(list);" } diff --git a/html-generators/README.md b/html-generators/README.md index 124a667..d5e14cc 100644 --- a/html-generators/README.md +++ b/html-generators/README.md @@ -10,6 +10,7 @@ This folder contains the build scripts that generate all HTML detail pages and ` | `generate.py` | Python equivalent — produces identical output | | `generate.jar` | Pre-built fat JAR (no JBang/JDK setup needed) | | `build-cds.sh` | Script to build a platform-specific AOT cache | +| `proof.java` | JBang script (Java 25) — runs all `proofCode` snippets via JShell | ## Benchmark @@ -65,10 +66,12 @@ This produces a self-contained ~2.2 MB JAR with all dependencies (Jackson) bundl ## CI/CD Workflows -Two GitHub Actions workflows automate the build and deploy pipeline: +Three GitHub Actions workflows automate the build, deploy, and proof pipeline: 1. **`build-generator.yml`** — Triggered when `generate.java` changes on `main`. Uses JBang to rebuild the fat JAR and commits the updated `generate.jar` back to the repository. 2. **`deploy.yml`** — Triggered when content, templates, the JAR, or site assets change on `main`. Runs `java -jar html-generators/generate.jar` to regenerate all HTML pages, `snippets.json`, and `index.html`, then deploys the `site/` folder to GitHub Pages. +3. **`proof.yml`** — Triggered when content changes on `main` or in pull requests. Runs `jbang html-generators/proof.java` to verify all `proofCode` snippets compile and execute correctly via JShell. + This means the deploy workflow always uses the pre-built fat JAR (no JBang required at deploy time), and the JAR stays in sync with the source automatically. diff --git a/html-generators/generate.java b/html-generators/generate.java index edab941..502155e 100644 --- a/html-generators/generate.java +++ b/html-generators/generate.java @@ -122,7 +122,7 @@ static Map loadStrings(String locale) throws IOException { return merged; } -static final Set EXCLUDED_KEYS = Set.of("_path", "prev", "next", "related"); +static final Set EXCLUDED_KEYS = Set.of("_path", "prev", "next", "related", "proofCode"); record Snippet(JsonNode node) { String get(String f) { return node.get(f).asText(); } diff --git a/html-generators/generate.py b/html-generators/generate.py index 0c7ea77..4a00e36 100644 --- a/html-generators/generate.py +++ b/html-generators/generate.py @@ -25,7 +25,7 @@ TOKEN_RE = re.compile(r"\{\{([\w.]+)\}\}") -EXCLUDED_KEYS = {"_path", "prev", "next", "related"} +EXCLUDED_KEYS = {"_path", "prev", "next", "related", "proofCode"} TRANSLATABLE_FIELDS = { "title", "summary", "explanation", "oldApproach", "modernApproach", diff --git a/html-generators/proof.java b/html-generators/proof.java new file mode 100644 index 0000000..96f4b79 --- /dev/null +++ b/html-generators/proof.java @@ -0,0 +1,167 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25 +//DEPS com.fasterxml.jackson.core:jackson-databind:2.18.3 +//DEPS com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.18.3 + +import module java.base; +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; + +/** + * Runs all proofCode snippets found in content/**\/\*.yaml through JShell to verify + * they compile and execute without errors. + * + * Usage: + * jbang html-generators/proof.java # run all proofCode snippets + * jbang html-generators/proof.java --list # list patterns with/without proofCode + */ +static final String CONTENT_DIR = "content"; +static final ObjectMapper YAML_MAPPER = new ObjectMapper(new YAMLFactory()); + +/** Determine the JShell executable path from the running JDK */ +static String jshellPath() { + var javaHome = System.getProperty("java.home"); + var jshell = Path.of(javaHome, "bin", "jshell"); + if (Files.exists(jshell)) return jshell.toString(); + return "jshell"; // fall back to PATH +} + +void main(String... args) throws Exception { + boolean listMode = args.length > 0 && args[0].equals("--list"); + + var contentDir = Path.of(CONTENT_DIR); + if (!Files.isDirectory(contentDir)) { + IO.println("ERROR: content directory not found. Run from the repository root."); + System.exit(1); + } + + var yamlFiles = Files.walk(contentDir) + .filter(p -> { + var name = p.getFileName().toString(); + return name.endsWith(".yaml") || name.endsWith(".yml"); + }) + .sorted() + .toList(); + + if (listMode) { + listPatterns(yamlFiles); + return; + } + + int passed = 0, failed = 0, skipped = 0; + var failures = new ArrayList(); + + for (var file : yamlFiles) { + JsonNode node; + try { + node = YAML_MAPPER.readTree(file.toFile()); + } catch (Exception e) { + IO.println("WARN: Could not parse " + file + ": " + e.getMessage()); + continue; + } + + var proofNode = node.get("proofCode"); + if (proofNode == null || proofNode.isNull() || proofNode.asText().isBlank()) { + skipped++; + continue; + } + + var slug = node.has("slug") ? node.get("slug").asText() : file.getFileName().toString(); + var category = node.has("category") ? node.get("category").asText() : "unknown"; + var proofCode = proofNode.asText(); + + System.out.print(" [" + category + "/" + slug + "] "); + + try { + // Pipe proofCode + /exit via stdin so JShell exits automatically + var proc = new ProcessBuilder(jshellPath(), "--feedback", "concise", "-") + .redirectErrorStream(true) + .start(); + + try (var stdin = proc.getOutputStream()) { + stdin.write((proofCode + "\n/exit\n").getBytes(java.nio.charset.StandardCharsets.UTF_8)); + } + + var output = proc.inputReader().lines().collect(java.util.stream.Collectors.joining("\n")); + proc.waitFor(30, TimeUnit.SECONDS); + + if (isFailure(output)) { + IO.println("FAILED"); + // Print the output indented for readability + for (var line : output.split("\n")) { + if (!line.isBlank()) IO.println(" " + line); + } + failed++; + failures.add(category + "/" + slug); + } else { + IO.println("OK"); + passed++; + } + } catch (Exception e) { + IO.println("ERROR: " + e.getMessage()); + failed++; + failures.add(category + "/" + slug); + } + } + + IO.println(""); + IO.println("Results: %d passed, %d failed, %d skipped (no proofCode)".formatted(passed, failed, skipped)); + + if (failed > 0) { + IO.println(""); + IO.println("Failed patterns:"); + for (var f : failures) IO.println(" - " + f); + System.exit(1); + } +} + +/** Returns true if the JShell output indicates a compile or runtime error */ +static boolean isFailure(String output) { + for (var line : output.split("\n")) { + var stripped = line.strip(); + if (stripped.startsWith("Error:") || stripped.startsWith("| Error")) return true; + if (stripped.startsWith("Exception ") && stripped.contains(".")) return true; + } + return false; +} + +/** Lists all patterns and whether they have proofCode */ +static void listPatterns(List yamlFiles) throws Exception { + int withProof = 0, withoutProof = 0; + IO.println("Patterns with proofCode:"); + for (var file : yamlFiles) { + JsonNode node; + try { + node = YAML_MAPPER.readTree(file.toFile()); + } catch (Exception e) { + continue; + } + var slug = node.has("slug") ? node.get("slug").asText() : file.toString(); + var category = node.has("category") ? node.get("category").asText() : "?"; + var hasProof = node.has("proofCode") && !node.get("proofCode").isNull() + && !node.get("proofCode").asText().isBlank(); + if (hasProof) { + IO.println(" [x] " + category + "/" + slug); + withProof++; + } else { + withoutProof++; + } + } + IO.println(""); + IO.println("Patterns without proofCode (%d):".formatted(withoutProof)); + for (var file : yamlFiles) { + JsonNode node; + try { + node = YAML_MAPPER.readTree(file.toFile()); + } catch (Exception e) { + continue; + } + var slug = node.has("slug") ? node.get("slug").asText() : file.toString(); + var category = node.has("category") ? node.get("category").asText() : "?"; + var hasProof = node.has("proofCode") && !node.get("proofCode").isNull() + && !node.get("proofCode").asText().isBlank(); + if (!hasProof) IO.println(" [ ] " + category + "/" + slug); + } + IO.println(""); + IO.println("Total: %d with proofCode, %d without".formatted(withProof, withoutProof)); +} From 16567bd8ffa8bff65e8a13c078ef1d5a7cf58263 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 23:24:13 +0000 Subject: [PATCH 27/28] Fix text block assertion to check for real newlines instead of absence of escaped ones Co-authored-by: brunoborges <129743+brunoborges@users.noreply.github.com> --- content/language/text-blocks-for-multiline-strings.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/language/text-blocks-for-multiline-strings.yaml b/content/language/text-blocks-for-multiline-strings.yaml index 8bce5e6..ec1598c 100644 --- a/content/language/text-blocks-for-multiline-strings.yaml +++ b/content/language/text-blocks-for-multiline-strings.yaml @@ -56,5 +56,5 @@ proofCode: |- "age": 30 }"""; if (!json.contains("Duke")) throw new AssertionError("text block content missing"); - if (json.contains("\\n")) throw new AssertionError("should not contain literal \\n"); + if (!json.contains("\n")) throw new AssertionError("text block should contain real newlines"); IO.println("text blocks: OK"); From 25640516948fec500dedc0b8e02dc814aed6c66f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 23:44:53 +0000 Subject: [PATCH 28/28] Rework proof script to use existing proof/ Java files instead of YAML proofCode The existing proof/ directory (from a parallel branch) contains 105 individual JBang scripts - one per pattern - that were missed in the initial approach. Changes: - Add all 105 proof/**/*.java scripts from proof/ directory - Rewrite html-generators/proof.java to run proof/**/*.java via jbang instead of parsing YAML proofCode fields through JShell - Revert the proofCode field additions from 10 YAML content files - Revert proofCode from generate.java/generate.py EXCLUDED_KEYS - Revert proofCode from content/template.json - Update .github/workflows/proof.yml to trigger on proof/** changes - Update html-generators/README.md, CONTRIBUTING.md, and .github/copilot-instructions.md to document the proof/ directory Co-authored-by: brunoborges <129743+brunoborges@users.noreply.github.com> --- .github/copilot-instructions.md | 10 +- .github/workflows/proof.yml | 4 +- CONTRIBUTING.md | 2 +- .../collections/immutable-list-creation.yaml | 8 - content/concurrency/virtual-threads.yaml | 10 -- content/datetime/java-time-basics.yaml | 9 - .../language/pattern-matching-instanceof.yaml | 8 - .../language/records-for-data-classes.yaml | 5 - content/language/switch-expressions.yaml | 9 - .../text-blocks-for-multiline-strings.yaml | 9 - content/language/type-inference-with-var.yaml | 7 - content/streams/stream-tolist.yaml | 4 - content/strings/string-isblank.yaml | 5 - content/template.json | 3 +- html-generators/README.md | 4 +- html-generators/generate.java | 2 +- html-generators/generate.py | 2 +- html-generators/proof.java | 167 +++++++----------- proof/collections/CollectorsTeeing.java | 21 +++ .../CopyingCollectionsImmutably.java | 11 ++ proof/collections/ImmutableListCreation.java | 10 ++ proof/collections/ImmutableMapCreation.java | 10 ++ proof/collections/ImmutableSetCreation.java | 10 ++ proof/collections/MapEntryFactory.java | 9 + proof/collections/ReverseListIteration.java | 12 ++ proof/collections/SequencedCollections.java | 12 ++ proof/collections/StreamToarrayTyped.java | 16 ++ proof/collections/UnmodifiableCollectors.java | 11 ++ .../CompletablefutureChaining.java | 16 ++ proof/concurrency/ConcurrentHttpVirtual.java | 34 ++++ .../concurrency/ExecutorTryWithResources.java | 14 ++ proof/concurrency/LockFreeLazyInit.java | 28 +++ proof/concurrency/ProcessApi.java | 13 ++ proof/concurrency/ScopedValues.java | 31 ++++ proof/concurrency/StableValues.java | 29 +++ proof/concurrency/StructuredConcurrency.java | 24 +++ proof/concurrency/ThreadSleepDuration.java | 14 ++ proof/concurrency/VirtualThreads.java | 9 + proof/datetime/DateFormatting.java | 15 ++ proof/datetime/DurationAndPeriod.java | 20 +++ proof/datetime/HexFormat.java | 13 ++ proof/datetime/InstantPrecision.java | 12 ++ proof/datetime/JavaTimeBasics.java | 13 ++ proof/datetime/MathClamp.java | 10 ++ .../EjbTimerVsJakartaScheduler.java | 34 ++++ proof/enterprise/EjbVsCdi.java | 29 +++ .../JdbcResultsetVsJpaCriteria.java | 33 ++++ proof/enterprise/JdbcVsJooq.java | 37 ++++ proof/enterprise/JdbcVsJpa.java | 31 ++++ .../enterprise/JndiLookupVsCdiInjection.java | 32 ++++ proof/enterprise/JpaVsJakartaData.java | 19 ++ .../enterprise/JsfManagedBeanVsCdiNamed.java | 30 ++++ .../ManualTransactionVsDeclarative.java | 35 ++++ proof/enterprise/MdbVsReactiveMessaging.java | 25 +++ proof/enterprise/ServletVsJaxrs.java | 22 +++ .../SingletonEjbVsCdiApplicationScoped.java | 34 ++++ proof/enterprise/SoapVsJakartaRest.java | 34 ++++ proof/enterprise/SpringApiVersioning.java | 46 +++++ .../enterprise/SpringNullSafetyJspecify.java | 36 ++++ .../SpringXmlConfigVsAnnotations.java | 41 +++++ proof/errors/MultiCatch.java | 20 +++ proof/errors/NullInSwitch.java | 19 ++ proof/errors/OptionalChaining.java | 19 ++ proof/errors/OptionalOrelsethrow.java | 11 ++ proof/errors/RecordBasedErrors.java | 19 ++ proof/errors/RequireNonnullElse.java | 13 ++ proof/io/DeserializationFilters.java | 22 +++ proof/io/FileMemoryMapping.java | 26 +++ proof/io/FilesMismatch.java | 15 ++ proof/io/HttpClient.java | 17 ++ proof/io/InputstreamTransferto.java | 13 ++ proof/io/IoClassConsoleIo.java | 8 + proof/io/PathOf.java | 10 ++ proof/io/ReadingFiles.java | 12 ++ .../io/TryWithResourcesEffectivelyFinal.java | 21 +++ proof/io/WritingFiles.java | 13 ++ .../language/CompactCanonicalConstructor.java | 17 ++ proof/language/CompactSourceFiles.java | 7 + proof/language/DefaultInterfaceMethods.java | 26 +++ proof/language/DiamondOperator.java | 16 ++ proof/language/ExhaustiveSwitch.java | 22 +++ proof/language/FlexibleConstructorBodies.java | 23 +++ proof/language/GuardedPatterns.java | 24 +++ proof/language/MarkdownJavadocComments.java | 23 +++ proof/language/ModuleImportDeclarations.java | 12 ++ proof/language/PatternMatchingInstanceof.java | 10 ++ proof/language/PatternMatchingSwitch.java | 18 ++ proof/language/PrimitiveTypesInPatterns.java | 21 +++ proof/language/PrivateInterfaceMethods.java | 22 +++ proof/language/RecordPatterns.java | 12 ++ proof/language/RecordsForDataClasses.java | 9 + proof/language/SealedClasses.java | 14 ++ .../language/StaticMembersInInnerClasses.java | 20 +++ proof/language/StaticMethodsInInterfaces.java | 20 +++ proof/language/SwitchExpressions.java | 15 ++ .../TextBlocksForMultilineStrings.java | 11 ++ proof/language/TypeInferenceWithVar.java | 12 ++ proof/language/UnnamedVariables.java | 21 +++ proof/security/KeyDerivationFunctions.java | 23 +++ proof/security/PemEncoding.java | 20 +++ proof/security/RandomGenerator.java | 15 ++ proof/security/StrongRandom.java | 13 ++ proof/security/TlsDefault.java | 14 ++ proof/streams/CollectorsFlatmapping.java | 24 +++ proof/streams/OptionalIfpresentorelse.java | 22 +++ proof/streams/OptionalOr.java | 17 ++ proof/streams/PredicateNot.java | 13 ++ proof/streams/StreamGatherers.java | 15 ++ proof/streams/StreamIteratePredicate.java | 14 ++ proof/streams/StreamMapmulti.java | 24 +++ proof/streams/StreamOfNullable.java | 11 ++ proof/streams/StreamTakewhileDropwhile.java | 14 ++ proof/streams/StreamTolist.java | 12 ++ proof/streams/VirtualThreadExecutor.java | 18 ++ proof/strings/StringCharsStream.java | 12 ++ proof/strings/StringFormatted.java | 11 ++ proof/strings/StringIndentTransform.java | 12 ++ proof/strings/StringIsblank.java | 9 + proof/strings/StringLines.java | 8 + proof/strings/StringRepeat.java | 8 + proof/strings/StringStrip.java | 11 ++ proof/tooling/BuiltInHttpServer.java | 16 ++ proof/tooling/Junit6WithJspecify.java | 44 +++++ 123 files changed, 2042 insertions(+), 194 deletions(-) create mode 100755 proof/collections/CollectorsTeeing.java create mode 100755 proof/collections/CopyingCollectionsImmutably.java create mode 100755 proof/collections/ImmutableListCreation.java create mode 100755 proof/collections/ImmutableMapCreation.java create mode 100755 proof/collections/ImmutableSetCreation.java create mode 100755 proof/collections/MapEntryFactory.java create mode 100755 proof/collections/ReverseListIteration.java create mode 100755 proof/collections/SequencedCollections.java create mode 100755 proof/collections/StreamToarrayTyped.java create mode 100755 proof/collections/UnmodifiableCollectors.java create mode 100755 proof/concurrency/CompletablefutureChaining.java create mode 100755 proof/concurrency/ConcurrentHttpVirtual.java create mode 100755 proof/concurrency/ExecutorTryWithResources.java create mode 100755 proof/concurrency/LockFreeLazyInit.java create mode 100755 proof/concurrency/ProcessApi.java create mode 100755 proof/concurrency/ScopedValues.java create mode 100755 proof/concurrency/StableValues.java create mode 100755 proof/concurrency/StructuredConcurrency.java create mode 100755 proof/concurrency/ThreadSleepDuration.java create mode 100755 proof/concurrency/VirtualThreads.java create mode 100755 proof/datetime/DateFormatting.java create mode 100755 proof/datetime/DurationAndPeriod.java create mode 100755 proof/datetime/HexFormat.java create mode 100755 proof/datetime/InstantPrecision.java create mode 100755 proof/datetime/JavaTimeBasics.java create mode 100755 proof/datetime/MathClamp.java create mode 100755 proof/enterprise/EjbTimerVsJakartaScheduler.java create mode 100755 proof/enterprise/EjbVsCdi.java create mode 100755 proof/enterprise/JdbcResultsetVsJpaCriteria.java create mode 100755 proof/enterprise/JdbcVsJooq.java create mode 100755 proof/enterprise/JdbcVsJpa.java create mode 100755 proof/enterprise/JndiLookupVsCdiInjection.java create mode 100755 proof/enterprise/JpaVsJakartaData.java create mode 100755 proof/enterprise/JsfManagedBeanVsCdiNamed.java create mode 100755 proof/enterprise/ManualTransactionVsDeclarative.java create mode 100755 proof/enterprise/MdbVsReactiveMessaging.java create mode 100755 proof/enterprise/ServletVsJaxrs.java create mode 100755 proof/enterprise/SingletonEjbVsCdiApplicationScoped.java create mode 100755 proof/enterprise/SoapVsJakartaRest.java create mode 100755 proof/enterprise/SpringApiVersioning.java create mode 100755 proof/enterprise/SpringNullSafetyJspecify.java create mode 100755 proof/enterprise/SpringXmlConfigVsAnnotations.java create mode 100755 proof/errors/MultiCatch.java create mode 100755 proof/errors/NullInSwitch.java create mode 100755 proof/errors/OptionalChaining.java create mode 100755 proof/errors/OptionalOrelsethrow.java create mode 100755 proof/errors/RecordBasedErrors.java create mode 100755 proof/errors/RequireNonnullElse.java create mode 100755 proof/io/DeserializationFilters.java create mode 100755 proof/io/FileMemoryMapping.java create mode 100755 proof/io/FilesMismatch.java create mode 100755 proof/io/HttpClient.java create mode 100755 proof/io/InputstreamTransferto.java create mode 100755 proof/io/IoClassConsoleIo.java create mode 100755 proof/io/PathOf.java create mode 100755 proof/io/ReadingFiles.java create mode 100755 proof/io/TryWithResourcesEffectivelyFinal.java create mode 100755 proof/io/WritingFiles.java create mode 100755 proof/language/CompactCanonicalConstructor.java create mode 100755 proof/language/CompactSourceFiles.java create mode 100755 proof/language/DefaultInterfaceMethods.java create mode 100755 proof/language/DiamondOperator.java create mode 100755 proof/language/ExhaustiveSwitch.java create mode 100755 proof/language/FlexibleConstructorBodies.java create mode 100755 proof/language/GuardedPatterns.java create mode 100755 proof/language/MarkdownJavadocComments.java create mode 100755 proof/language/ModuleImportDeclarations.java create mode 100755 proof/language/PatternMatchingInstanceof.java create mode 100755 proof/language/PatternMatchingSwitch.java create mode 100755 proof/language/PrimitiveTypesInPatterns.java create mode 100755 proof/language/PrivateInterfaceMethods.java create mode 100755 proof/language/RecordPatterns.java create mode 100755 proof/language/RecordsForDataClasses.java create mode 100755 proof/language/SealedClasses.java create mode 100755 proof/language/StaticMembersInInnerClasses.java create mode 100755 proof/language/StaticMethodsInInterfaces.java create mode 100755 proof/language/SwitchExpressions.java create mode 100755 proof/language/TextBlocksForMultilineStrings.java create mode 100755 proof/language/TypeInferenceWithVar.java create mode 100755 proof/language/UnnamedVariables.java create mode 100755 proof/security/KeyDerivationFunctions.java create mode 100755 proof/security/PemEncoding.java create mode 100755 proof/security/RandomGenerator.java create mode 100755 proof/security/StrongRandom.java create mode 100755 proof/security/TlsDefault.java create mode 100755 proof/streams/CollectorsFlatmapping.java create mode 100755 proof/streams/OptionalIfpresentorelse.java create mode 100755 proof/streams/OptionalOr.java create mode 100755 proof/streams/PredicateNot.java create mode 100755 proof/streams/StreamGatherers.java create mode 100755 proof/streams/StreamIteratePredicate.java create mode 100755 proof/streams/StreamMapmulti.java create mode 100755 proof/streams/StreamOfNullable.java create mode 100755 proof/streams/StreamTakewhileDropwhile.java create mode 100755 proof/streams/StreamTolist.java create mode 100755 proof/streams/VirtualThreadExecutor.java create mode 100755 proof/strings/StringCharsStream.java create mode 100755 proof/strings/StringFormatted.java create mode 100755 proof/strings/StringIndentTransform.java create mode 100755 proof/strings/StringIsblank.java create mode 100755 proof/strings/StringLines.java create mode 100755 proof/strings/StringRepeat.java create mode 100755 proof/strings/StringStrip.java create mode 100755 proof/tooling/BuiltInHttpServer.java create mode 100755 proof/tooling/Junit6WithJspecify.java diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 9244879..614a4f5 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -49,6 +49,10 @@ Run `jbang html-generators/generate.java` to rebuild all generated files from th ``` content/ # English content JSON files (source of truth, one per pattern) +proof/ # Proof scripts — one JBang .java file per pattern, proving it compiles + language/ # e.g. proof/language/TypeInferenceWithVar.java + collections/ # e.g. proof/collections/ImmutableListCreation.java + ... # mirrors content/ category structure translations/ # All i18n artifacts strings/ # UI strings per locale (en.yaml, es.yaml, pt-BR.yaml) content/ # Translated pattern files per locale (partial, translatable fields only) @@ -100,8 +104,7 @@ Each `content/category/slug.json` file has this structure: ], "docs": [ { "title": "Javadoc or Guide Title", "href": "https://docs.oracle.com/..." } - ], - "proofCode": "// Optional: self-contained JShell snippet proving the modern approach works.\n// Run with: jbang html-generators/proof.java" + ] } ``` @@ -139,7 +142,8 @@ Categories and their display names are defined in `html-generators/categories.pr 1. Create `content/category/new-slug.json` with all required fields 2. Update `prev`/`next` in the adjacent patterns' JSON files 3. Run `jbang html-generators/generate.java` -4. (Optional) Create translated content files under `translations/content/{locale}/category/new-slug.json` with only translatable fields — or let the AI translation workflow handle it +4. Add a proof script at `proof/category/SlugName.java` (JBang, `//JAVA 25+`) — run `jbang html-generators/proof.java` to verify +5. (Optional) Create translated content files under `translations/content/{locale}/category/new-slug.json` with only translatable fields — or let the AI translation workflow handle it ## Internationalization (i18n) diff --git a/.github/workflows/proof.yml b/.github/workflows/proof.yml index 46204f9..39e1c0d 100644 --- a/.github/workflows/proof.yml +++ b/.github/workflows/proof.yml @@ -4,12 +4,12 @@ on: push: branches: [main] paths: - - 'content/**' + - 'proof/**' - 'html-generators/proof.java' - '.github/workflows/proof.yml' pull_request: paths: - - 'content/**' + - 'proof/**' - 'html-generators/proof.java' workflow_dispatch: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 48e7fc1..2b6cd5b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,7 @@ Contributions are welcome! Content is managed as YAML files — never edit gener 3. Copy [`content/template.json`](content/template.json) as a starting point for all required fields (see the [snippet schema](.github/copilot-instructions.md) for details) 4. Update the `prev`/`next` fields in adjacent pattern files to maintain navigation 5. Run `jbang html-generators/generate.java` to verify your changes build correctly -6. Optionally add a `proofCode` field — a self-contained JShell snippet that proves the modern approach works. Run `jbang html-generators/proof.java` to validate it. +6. Add a proof script at `proof//SlugName.java` that uses the modern approach and run `jbang html-generators/proof.java` to verify it passes 7. Open a pull request Please ensure JDK version labels only reference the version where a feature became **final** (non-preview). diff --git a/content/collections/immutable-list-creation.yaml b/content/collections/immutable-list-creation.yaml index c49094d..0b33dca 100644 --- a/content/collections/immutable-list-creation.yaml +++ b/content/collections/immutable-list-creation.yaml @@ -47,11 +47,3 @@ docs: href: "https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/List.html#of()" - title: "Collections Factory Methods (JEP 269)" href: "https://openjdk.org/jeps/269" -proofCode: |- - var list = List.of("a", "b", "c"); - if (list.size() != 3) throw new AssertionError("expected 3 elements"); - try { - list.add("d"); - throw new AssertionError("should have thrown UnsupportedOperationException"); - } catch (UnsupportedOperationException ok) {} - IO.println("immutable list: OK - " + list); diff --git a/content/concurrency/virtual-threads.yaml b/content/concurrency/virtual-threads.yaml index 0970c44..3e5e6ab 100644 --- a/content/concurrency/virtual-threads.yaml +++ b/content/concurrency/virtual-threads.yaml @@ -47,13 +47,3 @@ docs: href: "https://openjdk.org/jeps/444" - title: "Thread.ofVirtual()" href: "https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/Thread.html#ofVirtual()" -proofCode: |- - var results = new java.util.concurrent.CopyOnWriteArrayList(); - var threads = new ArrayList(); - for (int i = 0; i < 5; i++) { - int idx = i; - threads.add(Thread.startVirtualThread(() -> results.add("vt-" + idx))); - } - for (var t : threads) t.join(); - if (results.size() != 5) throw new AssertionError("expected 5 results, got: " + results.size()); - IO.println("virtual threads: OK - " + results.size() + " threads ran"); diff --git a/content/datetime/java-time-basics.yaml b/content/datetime/java-time-basics.yaml index cdc29c9..0b11f4d 100644 --- a/content/datetime/java-time-basics.yaml +++ b/content/datetime/java-time-basics.yaml @@ -51,12 +51,3 @@ docs: href: "https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/time/LocalTime.html" - title: "LocalDateTime" href: "https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/time/LocalDateTime.html" -proofCode: |- - import java.time.*; - var date = LocalDate.of(2025, Month.JANUARY, 15); - var time = LocalTime.of(14, 30); - if (date.getMonthValue() != 1) throw new AssertionError("expected January=1, got: " + date.getMonthValue()); - if (time.getHour() != 14) throw new AssertionError("expected hour=14, got: " + time.getHour()); - var now = Instant.now(); - if (now == null) throw new AssertionError("Instant.now() returned null"); - IO.println("java.time basics: OK - " + date + " " + time); diff --git a/content/language/pattern-matching-instanceof.yaml b/content/language/pattern-matching-instanceof.yaml index 9318d87..d4306b7 100644 --- a/content/language/pattern-matching-instanceof.yaml +++ b/content/language/pattern-matching-instanceof.yaml @@ -44,11 +44,3 @@ related: docs: - title: "Pattern Matching for instanceof (JEP 394)" href: "https://openjdk.org/jeps/394" -proofCode: |- - Object obj = "Hello, pattern matching!"; - if (obj instanceof String s) { - IO.println("length=" + s.length()); - } else { - throw new AssertionError("should have matched String"); - } - IO.println("pattern matching instanceof: OK"); diff --git a/content/language/records-for-data-classes.yaml b/content/language/records-for-data-classes.yaml index ee9e661..bcc1bc0 100644 --- a/content/language/records-for-data-classes.yaml +++ b/content/language/records-for-data-classes.yaml @@ -46,8 +46,3 @@ docs: href: "https://openjdk.org/jeps/395" - title: "Record class" href: "https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/Record.html" -proofCode: |- - public record Point(int x, int y) {} - var p = new Point(1, 2); - if (p.x() != 1 || p.y() != 2) throw new AssertionError("accessor mismatch"); - IO.println("records: OK - " + p); diff --git a/content/language/switch-expressions.yaml b/content/language/switch-expressions.yaml index 0726089..5e099c4 100644 --- a/content/language/switch-expressions.yaml +++ b/content/language/switch-expressions.yaml @@ -53,12 +53,3 @@ related: docs: - title: "Switch Expressions (JEP 361)" href: "https://openjdk.org/jeps/361" -proofCode: |- - var day = "MONDAY"; - String msg = switch (day) { - case "MONDAY" -> "Start"; - case "FRIDAY" -> "End"; - default -> "Mid"; - }; - if (!"Start".equals(msg)) throw new AssertionError("unexpected: " + msg); - IO.println("switch expressions: OK - " + msg); diff --git a/content/language/text-blocks-for-multiline-strings.yaml b/content/language/text-blocks-for-multiline-strings.yaml index ec1598c..dd358c0 100644 --- a/content/language/text-blocks-for-multiline-strings.yaml +++ b/content/language/text-blocks-for-multiline-strings.yaml @@ -49,12 +49,3 @@ docs: href: "https://openjdk.org/jeps/378" - title: "Text Blocks Guide" href: "https://docs.oracle.com/en/java/javase/25/language/text-blocks.html" -proofCode: |- - String json = """ - { - "name": "Duke", - "age": 30 - }"""; - if (!json.contains("Duke")) throw new AssertionError("text block content missing"); - if (!json.contains("\n")) throw new AssertionError("text block should contain real newlines"); - IO.println("text blocks: OK"); diff --git a/content/language/type-inference-with-var.yaml b/content/language/type-inference-with-var.yaml index 8bc5be4..4eba7d4 100644 --- a/content/language/type-inference-with-var.yaml +++ b/content/language/type-inference-with-var.yaml @@ -49,10 +49,3 @@ docs: href: "https://openjdk.org/jeps/286" - title: "Style Guidelines for var" href: "https://openjdk.org/projects/amber/guides/lvti-style-guide" -proofCode: |- - var map = new HashMap>(); - map.put("a", List.of(1, 2, 3)); - for (var entry : map.entrySet()) { - IO.println("key=" + entry.getKey() + " value=" + entry.getValue()); - } - IO.println("var: OK"); diff --git a/content/streams/stream-tolist.yaml b/content/streams/stream-tolist.yaml index 0d4ef2b..5536c3a 100644 --- a/content/streams/stream-tolist.yaml +++ b/content/streams/stream-tolist.yaml @@ -42,7 +42,3 @@ related: docs: - title: "Stream.toList()" href: "https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/stream/Stream.html#toList()" -proofCode: |- - var result = Stream.of("hello", "world", "java", "go").filter(s -> s.length() > 3).toList(); - if (result.size() != 3) throw new AssertionError("expected 3 elements, got: " + result); - IO.println("stream.toList(): OK - " + result); diff --git a/content/strings/string-isblank.yaml b/content/strings/string-isblank.yaml index b656b83..7969721 100644 --- a/content/strings/string-isblank.yaml +++ b/content/strings/string-isblank.yaml @@ -41,8 +41,3 @@ related: docs: - title: "String.isBlank()" href: "https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/String.html#isBlank()" -proofCode: |- - if (!" ".isBlank()) throw new AssertionError("spaces should be blank"); - if (!"".isBlank()) throw new AssertionError("empty string should be blank"); - if ("hello".isBlank()) throw new AssertionError("non-empty string should not be blank"); - IO.println("String.isBlank(): OK"); diff --git a/content/template.json b/content/template.json index 504a407..8a7da6d 100644 --- a/content/template.json +++ b/content/template.json @@ -46,6 +46,5 @@ "title": "Javadoc or Guide Title", "href": "https://docs.oracle.com/..." } - ], - "proofCode": "// Optional: a self-contained JShell snippet that proves the modern approach works.\n// Run all proofCode snippets with: jbang html-generators/proof.java\n// Example: var list = List.of(\"a\", \"b\", \"c\"); IO.println(list);" + ] } diff --git a/html-generators/README.md b/html-generators/README.md index d5e14cc..0583c45 100644 --- a/html-generators/README.md +++ b/html-generators/README.md @@ -10,7 +10,7 @@ This folder contains the build scripts that generate all HTML detail pages and ` | `generate.py` | Python equivalent — produces identical output | | `generate.jar` | Pre-built fat JAR (no JBang/JDK setup needed) | | `build-cds.sh` | Script to build a platform-specific AOT cache | -| `proof.java` | JBang script (Java 25) — runs all `proofCode` snippets via JShell | +| `proof.java` | JBang script (Java 25) — runs all `proof/**/*.java` scripts via JBang | ## Benchmark @@ -72,6 +72,6 @@ Three GitHub Actions workflows automate the build, deploy, and proof pipeline: 2. **`deploy.yml`** — Triggered when content, templates, the JAR, or site assets change on `main`. Runs `java -jar html-generators/generate.jar` to regenerate all HTML pages, `snippets.json`, and `index.html`, then deploys the `site/` folder to GitHub Pages. -3. **`proof.yml`** — Triggered when content changes on `main` or in pull requests. Runs `jbang html-generators/proof.java` to verify all `proofCode` snippets compile and execute correctly via JShell. +3. **`proof.yml`** — Triggered when `proof/` scripts or content changes on `main` or in pull requests. Runs `jbang html-generators/proof.java` to verify all proof scripts compile and execute correctly. This means the deploy workflow always uses the pre-built fat JAR (no JBang required at deploy time), and the JAR stays in sync with the source automatically. diff --git a/html-generators/generate.java b/html-generators/generate.java index 502155e..edab941 100644 --- a/html-generators/generate.java +++ b/html-generators/generate.java @@ -122,7 +122,7 @@ static Map loadStrings(String locale) throws IOException { return merged; } -static final Set EXCLUDED_KEYS = Set.of("_path", "prev", "next", "related", "proofCode"); +static final Set EXCLUDED_KEYS = Set.of("_path", "prev", "next", "related"); record Snippet(JsonNode node) { String get(String f) { return node.get(f).asText(); } diff --git a/html-generators/generate.py b/html-generators/generate.py index 4a00e36..0c7ea77 100644 --- a/html-generators/generate.py +++ b/html-generators/generate.py @@ -25,7 +25,7 @@ TOKEN_RE = re.compile(r"\{\{([\w.]+)\}\}") -EXCLUDED_KEYS = {"_path", "prev", "next", "related", "proofCode"} +EXCLUDED_KEYS = {"_path", "prev", "next", "related"} TRANSLATABLE_FIELDS = { "title", "summary", "explanation", "oldApproach", "modernApproach", diff --git a/html-generators/proof.java b/html-generators/proof.java index 96f4b79..c483619 100644 --- a/html-generators/proof.java +++ b/html-generators/proof.java @@ -1,98 +1,90 @@ ///usr/bin/env jbang "$0" "$@" ; exit $? //JAVA 25 -//DEPS com.fasterxml.jackson.core:jackson-databind:2.18.3 -//DEPS com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.18.3 import module java.base; -import com.fasterxml.jackson.databind.*; -import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; /** - * Runs all proofCode snippets found in content/**\/\*.yaml through JShell to verify + * Runs all proof scripts found in proof/**\/\*.java through JBang to verify * they compile and execute without errors. * + * Each proof//SlugName.java is a standalone JBang script that + * demonstrates a modern Java pattern from the corresponding content YAML file. + * * Usage: - * jbang html-generators/proof.java # run all proofCode snippets - * jbang html-generators/proof.java --list # list patterns with/without proofCode + * jbang html-generators/proof.java # run all proof scripts + * jbang html-generators/proof.java --list # list all proof scripts */ -static final String CONTENT_DIR = "content"; -static final ObjectMapper YAML_MAPPER = new ObjectMapper(new YAMLFactory()); - -/** Determine the JShell executable path from the running JDK */ -static String jshellPath() { - var javaHome = System.getProperty("java.home"); - var jshell = Path.of(javaHome, "bin", "jshell"); - if (Files.exists(jshell)) return jshell.toString(); - return "jshell"; // fall back to PATH +static final String PROOF_DIR = "proof"; + +/** Find the jbang executable. Prefers JBANG env var, then PATH. */ +static String jbangPath() { + var envJbang = System.getenv("JBANG_HOME"); + if (envJbang != null) { + var p = Path.of(envJbang, "bin", "jbang"); + if (Files.exists(p)) return p.toString(); + } + // When proof.java is run via jbang, jbang itself is in PATH + return "jbang"; } void main(String... args) throws Exception { boolean listMode = args.length > 0 && args[0].equals("--list"); - var contentDir = Path.of(CONTENT_DIR); - if (!Files.isDirectory(contentDir)) { - IO.println("ERROR: content directory not found. Run from the repository root."); + var proofDir = Path.of(PROOF_DIR); + if (!Files.isDirectory(proofDir)) { + IO.println("ERROR: proof directory not found. Run from the repository root."); System.exit(1); } - var yamlFiles = Files.walk(contentDir) - .filter(p -> { - var name = p.getFileName().toString(); - return name.endsWith(".yaml") || name.endsWith(".yml"); - }) + var proofFiles = Files.walk(proofDir) + .filter(p -> p.toString().endsWith(".java")) .sorted() .toList(); - if (listMode) { - listPatterns(yamlFiles); - return; + if (proofFiles.isEmpty()) { + IO.println("No proof scripts found in " + PROOF_DIR + "/"); + System.exit(1); } - int passed = 0, failed = 0, skipped = 0; - var failures = new ArrayList(); - - for (var file : yamlFiles) { - JsonNode node; - try { - node = YAML_MAPPER.readTree(file.toFile()); - } catch (Exception e) { - IO.println("WARN: Could not parse " + file + ": " + e.getMessage()); - continue; + if (listMode) { + IO.println("Proof scripts (%d):".formatted(proofFiles.size())); + for (var file : proofFiles) { + var label = proofLabel(file); + IO.println(" " + label); } + return; + } - var proofNode = node.get("proofCode"); - if (proofNode == null || proofNode.isNull() || proofNode.asText().isBlank()) { - skipped++; - continue; - } + IO.println("Running %d proof scripts...".formatted(proofFiles.size())); + IO.println(""); - var slug = node.has("slug") ? node.get("slug").asText() : file.getFileName().toString(); - var category = node.has("category") ? node.get("category").asText() : "unknown"; - var proofCode = proofNode.asText(); + int passed = 0, failed = 0; + var failures = new ArrayList(); - System.out.print(" [" + category + "/" + slug + "] "); + for (var file : proofFiles) { + var label = proofLabel(file); + System.out.print(" [" + label + "] "); try { - // Pipe proofCode + /exit via stdin so JShell exits automatically - var proc = new ProcessBuilder(jshellPath(), "--feedback", "concise", "-") + var proc = new ProcessBuilder(jbangPath(), "--quiet", file.toString()) .redirectErrorStream(true) .start(); - try (var stdin = proc.getOutputStream()) { - stdin.write((proofCode + "\n/exit\n").getBytes(java.nio.charset.StandardCharsets.UTF_8)); - } - var output = proc.inputReader().lines().collect(java.util.stream.Collectors.joining("\n")); - proc.waitFor(30, TimeUnit.SECONDS); + boolean timedOut = !proc.waitFor(60, TimeUnit.SECONDS); - if (isFailure(output)) { + if (timedOut) { + proc.destroyForcibly(); + IO.println("TIMEOUT"); + failed++; + failures.add(label); + } else if (proc.exitValue() != 0) { IO.println("FAILED"); - // Print the output indented for readability for (var line : output.split("\n")) { if (!line.isBlank()) IO.println(" " + line); } failed++; - failures.add(category + "/" + slug); + failures.add(label); } else { IO.println("OK"); passed++; @@ -100,68 +92,27 @@ void main(String... args) throws Exception { } catch (Exception e) { IO.println("ERROR: " + e.getMessage()); failed++; - failures.add(category + "/" + slug); + failures.add(label); } } IO.println(""); - IO.println("Results: %d passed, %d failed, %d skipped (no proofCode)".formatted(passed, failed, skipped)); + IO.println("Results: %d passed, %d failed".formatted(passed, failed)); if (failed > 0) { IO.println(""); - IO.println("Failed patterns:"); + IO.println("Failed:"); for (var f : failures) IO.println(" - " + f); System.exit(1); } } -/** Returns true if the JShell output indicates a compile or runtime error */ -static boolean isFailure(String output) { - for (var line : output.split("\n")) { - var stripped = line.strip(); - if (stripped.startsWith("Error:") || stripped.startsWith("| Error")) return true; - if (stripped.startsWith("Exception ") && stripped.contains(".")) return true; - } - return false; -} - -/** Lists all patterns and whether they have proofCode */ -static void listPatterns(List yamlFiles) throws Exception { - int withProof = 0, withoutProof = 0; - IO.println("Patterns with proofCode:"); - for (var file : yamlFiles) { - JsonNode node; - try { - node = YAML_MAPPER.readTree(file.toFile()); - } catch (Exception e) { - continue; - } - var slug = node.has("slug") ? node.get("slug").asText() : file.toString(); - var category = node.has("category") ? node.get("category").asText() : "?"; - var hasProof = node.has("proofCode") && !node.get("proofCode").isNull() - && !node.get("proofCode").asText().isBlank(); - if (hasProof) { - IO.println(" [x] " + category + "/" + slug); - withProof++; - } else { - withoutProof++; - } - } - IO.println(""); - IO.println("Patterns without proofCode (%d):".formatted(withoutProof)); - for (var file : yamlFiles) { - JsonNode node; - try { - node = YAML_MAPPER.readTree(file.toFile()); - } catch (Exception e) { - continue; - } - var slug = node.has("slug") ? node.get("slug").asText() : file.toString(); - var category = node.has("category") ? node.get("category").asText() : "?"; - var hasProof = node.has("proofCode") && !node.get("proofCode").isNull() - && !node.get("proofCode").asText().isBlank(); - if (!hasProof) IO.println(" [ ] " + category + "/" + slug); - } - IO.println(""); - IO.println("Total: %d with proofCode, %d without".formatted(withProof, withoutProof)); +/** Derive a human-readable label from the proof file path, e.g. "language/TypeInferenceWithVar" */ +static String proofLabel(Path file) { + var parts = new ArrayList(); + var iter = Path.of(PROOF_DIR).relativize(file).iterator(); + while (iter.hasNext()) parts.add(iter.next().toString()); + var name = parts.getLast().replaceAll("\\.java$", ""); + var category = parts.size() > 1 ? parts.getFirst() : "?"; + return category + "/" + name; } diff --git a/proof/collections/CollectorsTeeing.java b/proof/collections/CollectorsTeeing.java new file mode 100755 index 0000000..b1e54dd --- /dev/null +++ b/proof/collections/CollectorsTeeing.java @@ -0,0 +1,21 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; +import java.util.stream.*; +import static java.util.stream.Collectors.*; + +/// Proof: collectors-teeing +/// Source: content/collections/collectors-teeing.yaml +record Item(String name, double price) {} +record Stats(long count, double total) {} + +void main() { + var items = List.of(new Item("a", 10.0), new Item("b", 20.0)); + var result = items.stream().collect( + Collectors.teeing( + Collectors.counting(), + Collectors.summingDouble(Item::price), + Stats::new + ) + ); +} diff --git a/proof/collections/CopyingCollectionsImmutably.java b/proof/collections/CopyingCollectionsImmutably.java new file mode 100755 index 0000000..dedeacf --- /dev/null +++ b/proof/collections/CopyingCollectionsImmutably.java @@ -0,0 +1,11 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; + +/// Proof: copying-collections-immutably +/// Source: content/collections/copying-collections-immutably.yaml +void main() { + List original = new ArrayList<>(List.of("a", "b", "c")); + List copy = + List.copyOf(original); +} diff --git a/proof/collections/ImmutableListCreation.java b/proof/collections/ImmutableListCreation.java new file mode 100755 index 0000000..7b6c05a --- /dev/null +++ b/proof/collections/ImmutableListCreation.java @@ -0,0 +1,10 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; + +/// Proof: immutable-list-creation +/// Source: content/collections/immutable-list-creation.yaml +void main() { + List list = + List.of("a", "b", "c"); +} diff --git a/proof/collections/ImmutableMapCreation.java b/proof/collections/ImmutableMapCreation.java new file mode 100755 index 0000000..860d652 --- /dev/null +++ b/proof/collections/ImmutableMapCreation.java @@ -0,0 +1,10 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; + +/// Proof: immutable-map-creation +/// Source: content/collections/immutable-map-creation.yaml +void main() { + Map map = + Map.of("a", 1, "b", 2, "c", 3); +} diff --git a/proof/collections/ImmutableSetCreation.java b/proof/collections/ImmutableSetCreation.java new file mode 100755 index 0000000..152528f --- /dev/null +++ b/proof/collections/ImmutableSetCreation.java @@ -0,0 +1,10 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; + +/// Proof: immutable-set-creation +/// Source: content/collections/immutable-set-creation.yaml +void main() { + Set set = + Set.of("a", "b", "c"); +} diff --git a/proof/collections/MapEntryFactory.java b/proof/collections/MapEntryFactory.java new file mode 100755 index 0000000..15cbba1 --- /dev/null +++ b/proof/collections/MapEntryFactory.java @@ -0,0 +1,9 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; + +/// Proof: map-entry-factory +/// Source: content/collections/map-entry-factory.yaml +void main() { + var e = Map.entry("key", 42); +} diff --git a/proof/collections/ReverseListIteration.java b/proof/collections/ReverseListIteration.java new file mode 100755 index 0000000..828807d --- /dev/null +++ b/proof/collections/ReverseListIteration.java @@ -0,0 +1,12 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; + +/// Proof: reverse-list-iteration +/// Source: content/collections/reverse-list-iteration.yaml +void main() { + List list = List.of("a", "b", "c"); + for (String element : list.reversed()) { + System.out.println(element); + } +} diff --git a/proof/collections/SequencedCollections.java b/proof/collections/SequencedCollections.java new file mode 100755 index 0000000..8534f86 --- /dev/null +++ b/proof/collections/SequencedCollections.java @@ -0,0 +1,12 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; + +/// Proof: sequenced-collections +/// Source: content/collections/sequenced-collections.yaml +void main() { + List list = new ArrayList<>(List.of("a", "b", "c")); + var last = list.getLast(); + var first = list.getFirst(); + var reversed = list.reversed(); +} diff --git a/proof/collections/StreamToarrayTyped.java b/proof/collections/StreamToarrayTyped.java new file mode 100755 index 0000000..1a2cd42 --- /dev/null +++ b/proof/collections/StreamToarrayTyped.java @@ -0,0 +1,16 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; +import java.util.stream.*; + +/// Proof: stream-toarray-typed +/// Source: content/collections/stream-toarray-typed.yaml +List getNames() { + return List.of("Alice", "Bob", "Charlie", "Dave"); +} + +void main() { + String[] arr = getNames().stream() + .filter(n -> n.length() > 3) + .toArray(String[]::new); +} diff --git a/proof/collections/UnmodifiableCollectors.java b/proof/collections/UnmodifiableCollectors.java new file mode 100755 index 0000000..26e5920 --- /dev/null +++ b/proof/collections/UnmodifiableCollectors.java @@ -0,0 +1,11 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; +import java.util.stream.*; + +/// Proof: unmodifiable-collectors +/// Source: content/collections/unmodifiable-collectors.yaml +void main() { + Stream stream = Stream.of("a", "b", "c"); + List list = stream.toList(); +} diff --git a/proof/concurrency/CompletablefutureChaining.java b/proof/concurrency/CompletablefutureChaining.java new file mode 100755 index 0000000..6f9c0ad --- /dev/null +++ b/proof/concurrency/CompletablefutureChaining.java @@ -0,0 +1,16 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.concurrent.*; + +/// Proof: completablefuture-chaining +/// Source: content/concurrency/completablefuture-chaining.yaml +String fetchData() { return "data"; } +String transform(String data) { return data.toUpperCase(); } + +void main() { + CompletableFuture.supplyAsync( + this::fetchData + ) + .thenApply(this::transform) + .thenAccept(System.out::println); +} diff --git a/proof/concurrency/ConcurrentHttpVirtual.java b/proof/concurrency/ConcurrentHttpVirtual.java new file mode 100755 index 0000000..2deafc2 --- /dev/null +++ b/proof/concurrency/ConcurrentHttpVirtual.java @@ -0,0 +1,34 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.net.*; +import java.net.http.*; +import java.util.*; +import java.util.concurrent.*; + +/// Proof: concurrent-http-virtual +/// Source: content/concurrency/concurrent-http-virtual.yaml +HttpRequest req(String url) throws Exception { + return HttpRequest.newBuilder(new URI(url)).build(); +} + +void main() throws Exception { + var client = HttpClient.newHttpClient(); + var urls = List.of(); // empty — proof is compile-only + try (var exec = Executors + .newVirtualThreadPerTaskExecutor()) { + var results = urls.stream() + .map(u -> exec.submit(() -> { + try { + return client.send(req(u), + HttpResponse.BodyHandlers.ofString()).body(); + } catch (Exception e) { + throw new RuntimeException(e); + } + })) + .toList().stream() + .map(f -> { + try { return f.get(); } + catch (Exception e) { throw new RuntimeException(e); } + }).toList(); + } +} diff --git a/proof/concurrency/ExecutorTryWithResources.java b/proof/concurrency/ExecutorTryWithResources.java new file mode 100755 index 0000000..3b4d397 --- /dev/null +++ b/proof/concurrency/ExecutorTryWithResources.java @@ -0,0 +1,14 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.concurrent.*; + +/// Proof: executor-try-with-resources +/// Source: content/concurrency/executor-try-with-resources.yaml +void main() throws Exception { + Runnable task = () -> System.out.println("task"); + try (var exec = + Executors.newCachedThreadPool()) { + exec.submit(task); + } + // auto shutdown + await on close +} diff --git a/proof/concurrency/LockFreeLazyInit.java b/proof/concurrency/LockFreeLazyInit.java new file mode 100755 index 0000000..4bb27ac --- /dev/null +++ b/proof/concurrency/LockFreeLazyInit.java @@ -0,0 +1,28 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//JAVAC_OPTIONS --enable-preview --release 25 +//JAVA_OPTIONS --enable-preview +import java.util.function.*; + +/// Proof: lock-free-lazy-init +/// Source: content/concurrency/lock-free-lazy-init.yaml +/// +/// Note: The snippet calls INST.get() on a StableValue. In JDK 25, +/// StableValue.supplier() returns a Supplier whose get() provides the same +/// lock-free lazy initialization semantics. +class Config { + private static final Supplier INST = + StableValue.supplier(Config::load); + + static Config get() { + return INST.get(); + } + + static Config load() { + return null; // placeholder — real load reads from disk/DB + } +} + +void main() { + Config.get(); +} diff --git a/proof/concurrency/ProcessApi.java b/proof/concurrency/ProcessApi.java new file mode 100755 index 0000000..b4615a0 --- /dev/null +++ b/proof/concurrency/ProcessApi.java @@ -0,0 +1,13 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: process-api +/// Source: content/concurrency/process-api.yaml +void main() { + ProcessHandle ph = + ProcessHandle.current(); + long pid = ph.pid(); + ph.info().command() + .ifPresent(System.out::println); + ph.children().forEach( + c -> System.out.println(c.pid())); +} diff --git a/proof/concurrency/ScopedValues.java b/proof/concurrency/ScopedValues.java new file mode 100755 index 0000000..6dbfe90 --- /dev/null +++ b/proof/concurrency/ScopedValues.java @@ -0,0 +1,31 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.concurrent.*; + +/// Proof: scoped-values +/// Source: content/concurrency/scoped-values.yaml +record User(String name) {} +record Request(String path) {} + +class Handler { + static final ScopedValue CURRENT = + ScopedValue.newInstance(); + + User authenticate(Request req) { + return new User("Alice"); + } + + void handle(Request req) { + ScopedValue.where(CURRENT, + authenticate(req) + ).run(this::process); + } + + void process() { + // use CURRENT.get() in scope + } +} + +void main() { + new Handler().handle(new Request("/")); +} diff --git a/proof/concurrency/StableValues.java b/proof/concurrency/StableValues.java new file mode 100755 index 0000000..90055b3 --- /dev/null +++ b/proof/concurrency/StableValues.java @@ -0,0 +1,29 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//JAVAC_OPTIONS --enable-preview --release 25 +//JAVA_OPTIONS --enable-preview +import java.util.function.*; +import java.util.logging.*; + +/// Proof: stable-values +/// Source: content/concurrency/stable-values.yaml +/// +/// Note: The snippet calls logger.get() on a StableValue. In JDK 25, +/// StableValue.supplier() returns a Supplier whose get() provides the same +/// lazy, thread-safe initialization semantics. +class LoggerHolder { + private final Supplier logger = + StableValue.supplier(this::createLogger); + + Logger getLogger() { + return logger.get(); + } + + Logger createLogger() { + return Logger.getLogger(getClass().getName()); + } +} + +void main() { + new LoggerHolder().getLogger(); +} diff --git a/proof/concurrency/StructuredConcurrency.java b/proof/concurrency/StructuredConcurrency.java new file mode 100755 index 0000000..e6818c1 --- /dev/null +++ b/proof/concurrency/StructuredConcurrency.java @@ -0,0 +1,24 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//JAVAC_OPTIONS --enable-preview --release 25 +//JAVA_OPTIONS --enable-preview +import java.util.concurrent.*; + +/// Proof: structured-concurrency +/// Source: content/concurrency/structured-concurrency.yaml +record User(String name) {} +record Order(String id) {} +record Result(User user, Order order) {} + +User fetchUser() { return new User("Alice"); } +Order fetchOrder() { return new Order("o1"); } +Result combine(User u, Order o) { return new Result(u, o); } + +void main() throws Exception { + try (var scope = StructuredTaskScope.open()) { + var u = scope.fork(this::fetchUser); + var o = scope.fork(this::fetchOrder); + scope.join(); + combine(u.get(), o.get()); + } +} diff --git a/proof/concurrency/ThreadSleepDuration.java b/proof/concurrency/ThreadSleepDuration.java new file mode 100755 index 0000000..17c6207 --- /dev/null +++ b/proof/concurrency/ThreadSleepDuration.java @@ -0,0 +1,14 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.time.*; + +/// Proof: thread-sleep-duration +/// Source: content/concurrency/thread-sleep-duration.yaml +void main() throws InterruptedException { + Thread.sleep( + Duration.ofMillis(1) + ); + Thread.sleep( + Duration.ofMillis(1) + ); +} diff --git a/proof/concurrency/VirtualThreads.java b/proof/concurrency/VirtualThreads.java new file mode 100755 index 0000000..46c1255 --- /dev/null +++ b/proof/concurrency/VirtualThreads.java @@ -0,0 +1,9 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: virtual-threads +/// Source: content/concurrency/virtual-threads.yaml +void main() throws InterruptedException { + Thread.startVirtualThread(() -> { + System.out.println("hello"); + }).join(); +} diff --git a/proof/datetime/DateFormatting.java b/proof/datetime/DateFormatting.java new file mode 100755 index 0000000..57d2327 --- /dev/null +++ b/proof/datetime/DateFormatting.java @@ -0,0 +1,15 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.time.*; +import java.time.format.*; + +/// Proof: date-formatting +/// Source: content/datetime/date-formatting.yaml +void main() { + DateTimeFormatter fmt = + DateTimeFormatter.ofPattern( + "uuuu-MM-dd"); + String formatted = + LocalDate.now().format(fmt); + // Thread-safe, immutable +} diff --git a/proof/datetime/DurationAndPeriod.java b/proof/datetime/DurationAndPeriod.java new file mode 100755 index 0000000..293b8c1 --- /dev/null +++ b/proof/datetime/DurationAndPeriod.java @@ -0,0 +1,20 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.time.*; +import java.time.temporal.*; + +/// Proof: duration-and-period +/// Source: content/datetime/duration-and-period.yaml +void main() { + LocalDate date1 = LocalDate.of(2024, 1, 1); + LocalDate date2 = LocalDate.of(2025, 1, 1); + LocalTime time1 = LocalTime.of(8, 0); + LocalTime time2 = LocalTime.of(17, 0); + + long days = ChronoUnit.DAYS + .between(date1, date2); + Period period = Period.between( + date1, date2); + Duration elapsed = Duration.between( + time1, time2); +} diff --git a/proof/datetime/HexFormat.java b/proof/datetime/HexFormat.java new file mode 100755 index 0000000..3f07818 --- /dev/null +++ b/proof/datetime/HexFormat.java @@ -0,0 +1,13 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: hex-format +/// Source: content/datetime/hex-format.yaml +void main() { + byte byteValue = 0x48; + var hex = HexFormat.of() + .withUpperCase(); + String s = hex.toHexDigits( + byteValue); + byte[] bytes = + hex.parseHex("48656C6C6F"); +} diff --git a/proof/datetime/InstantPrecision.java b/proof/datetime/InstantPrecision.java new file mode 100755 index 0000000..ae5d9fe --- /dev/null +++ b/proof/datetime/InstantPrecision.java @@ -0,0 +1,12 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.time.*; + +/// Proof: instant-precision +/// Source: content/datetime/instant-precision.yaml +void main() { + // Microsecond/nanosecond precision + Instant now = Instant.now(); + // 2025-02-15T20:12:25.678901234Z + long nanos = now.getNano(); +} diff --git a/proof/datetime/JavaTimeBasics.java b/proof/datetime/JavaTimeBasics.java new file mode 100755 index 0000000..60510e9 --- /dev/null +++ b/proof/datetime/JavaTimeBasics.java @@ -0,0 +1,13 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.time.*; + +/// Proof: java-time-basics +/// Source: content/datetime/java-time-basics.yaml +void main() { + LocalDate date = LocalDate.of( + 2025, Month.JANUARY, 15); + LocalTime time = LocalTime.of(14, 30); + Instant now = Instant.now(); + // immutable, thread-safe +} diff --git a/proof/datetime/MathClamp.java b/proof/datetime/MathClamp.java new file mode 100755 index 0000000..ef35ba3 --- /dev/null +++ b/proof/datetime/MathClamp.java @@ -0,0 +1,10 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: math-clamp +/// Source: content/datetime/math-clamp.yaml +void main() { + int value = 150; + int clamped = + Math.clamp(value, 0, 100); + // value constrained to [0, 100] +} diff --git a/proof/enterprise/EjbTimerVsJakartaScheduler.java b/proof/enterprise/EjbTimerVsJakartaScheduler.java new file mode 100755 index 0000000..720b9ba --- /dev/null +++ b/proof/enterprise/EjbTimerVsJakartaScheduler.java @@ -0,0 +1,34 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS jakarta.enterprise:jakarta.enterprise.cdi-api:4.1.0 +//DEPS jakarta.annotation:jakarta.annotation-api:3.0.0 +//DEPS jakarta.enterprise.concurrent:jakarta.enterprise.concurrent-api:3.1.0 + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.annotation.Resource; +import jakarta.annotation.PostConstruct; +import jakarta.enterprise.concurrent.ManagedScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/// Proof: ejb-timer-vs-jakarta-scheduler +/// Source: content/enterprise/ejb-timer-vs-jakarta-scheduler.yaml +@ApplicationScoped +class ReportGenerator { + @Resource + ManagedScheduledExecutorService scheduler; + + @PostConstruct + public void init() { + scheduler.scheduleAtFixedRate( + this::generateReport, + 0, 24, TimeUnit.HOURS); + } + + public void generateReport() { + buildDailyReport(); + } + + void buildDailyReport() {} +} + +void main() {} diff --git a/proof/enterprise/EjbVsCdi.java b/proof/enterprise/EjbVsCdi.java new file mode 100755 index 0000000..6e168d7 --- /dev/null +++ b/proof/enterprise/EjbVsCdi.java @@ -0,0 +1,29 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS jakarta.enterprise:jakarta.enterprise.cdi-api:4.1.0 +//DEPS jakarta.transaction:jakarta.transaction-api:2.0.1 + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; + +/// Proof: ejb-vs-cdi +/// Source: content/enterprise/ejb-vs-cdi.yaml +record Order(Object item) {} + +class InventoryService { + void reserve(Object item) {} +} + +@ApplicationScoped +class OrderService { + @Inject + private InventoryService inventory; + + @Transactional + public void placeOrder(Order order) { + inventory.reserve(order.item()); + } +} + +void main() {} diff --git a/proof/enterprise/JdbcResultsetVsJpaCriteria.java b/proof/enterprise/JdbcResultsetVsJpaCriteria.java new file mode 100755 index 0000000..f5bafc8 --- /dev/null +++ b/proof/enterprise/JdbcResultsetVsJpaCriteria.java @@ -0,0 +1,33 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS jakarta.persistence:jakarta.persistence-api:3.2.0 + +import jakarta.persistence.*; +import jakarta.persistence.criteria.*; +import java.util.*; + +/// Proof: jdbc-resultset-vs-jpa-criteria +/// Source: content/enterprise/jdbc-resultset-vs-jpa-criteria.yaml +class User { + String status; + int age; +} + +class UserRepository { + @PersistenceContext + EntityManager em; + + public List findActiveAboveAge( + String status, int minAge) { + var cb = em.getCriteriaBuilder(); + var cq = + cb.createQuery(User.class); + var root = cq.from(User.class); + cq.select(root).where( + cb.equal(root.get("status"), status), + cb.greaterThan(root.get("age"), minAge)); + return em.createQuery(cq).getResultList(); + } +} + +void main() {} diff --git a/proof/enterprise/JdbcVsJooq.java b/proof/enterprise/JdbcVsJooq.java new file mode 100755 index 0000000..eaf2265 --- /dev/null +++ b/proof/enterprise/JdbcVsJooq.java @@ -0,0 +1,37 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS org.jooq:jooq:3.20.11 + +import org.jooq.*; +import org.jooq.impl.DSL; +import javax.sql.DataSource; +import java.util.*; + +/// Proof: jdbc-vs-jooq +/// Source: content/enterprise/jdbc-vs-jooq.yaml +class User { + Long id; String name; String email; +} + +// Simulating the generated jOOQ table fields (normally produced by jOOQ codegen) +class USERS { + static final Field DEPARTMENT = DSL.field(DSL.name("department"), String.class); + static final Field SALARY = DSL.field(DSL.name("salary"), Integer.class); + static final Field ID = DSL.field(DSL.name("id"), Long.class); + static final Field NAME = DSL.field(DSL.name("name"), String.class); + static final Field EMAIL = DSL.field(DSL.name("email"), String.class); + static final Table TABLE = DSL.table(DSL.name("users")); +} + +List findByDept(DataSource ds, String department, int minSalary) { + DSLContext dsl = DSL.using(ds, SQLDialect.POSTGRES); + + return dsl + .select(USERS.ID, USERS.NAME, USERS.EMAIL) + .from(USERS.TABLE) + .where(USERS.DEPARTMENT.eq(department) + .and(USERS.SALARY.gt(minSalary))) + .fetchInto(User.class); +} + +void main() {} diff --git a/proof/enterprise/JdbcVsJpa.java b/proof/enterprise/JdbcVsJpa.java new file mode 100755 index 0000000..a38cd00 --- /dev/null +++ b/proof/enterprise/JdbcVsJpa.java @@ -0,0 +1,31 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS jakarta.persistence:jakarta.persistence-api:3.2.0 + +import jakarta.persistence.*; +import java.util.*; + +/// Proof: jdbc-vs-jpa +/// Source: content/enterprise/jdbc-vs-jpa.yaml +class User { + Long id; String name; +} + +class UserRepository { + @PersistenceContext + EntityManager em; + + public User findUser(Long id) { + return em.find(User.class, id); + } + + public List findByName(String name) { + return em.createQuery( + "SELECT u FROM User u WHERE u.name = :name", + User.class) + .setParameter("name", name) + .getResultList(); + } +} + +void main() {} diff --git a/proof/enterprise/JndiLookupVsCdiInjection.java b/proof/enterprise/JndiLookupVsCdiInjection.java new file mode 100755 index 0000000..91ee6e3 --- /dev/null +++ b/proof/enterprise/JndiLookupVsCdiInjection.java @@ -0,0 +1,32 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS jakarta.enterprise:jakarta.enterprise.cdi-api:4.1.0 +//DEPS jakarta.annotation:jakarta.annotation-api:3.0.0 + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.annotation.Resource; +import javax.sql.DataSource; +import java.sql.*; +import java.util.*; + +/// Proof: jndi-lookup-vs-cdi-injection +/// Source: content/enterprise/jndi-lookup-vs-cdi-injection.yaml +record Order(String id) {} + +@ApplicationScoped +class OrderService { + @Inject + @Resource(name = "jdbc/OrderDB") + DataSource ds; + + public List findAll() + throws SQLException { + try (Connection con = ds.getConnection()) { + // query orders + } + return List.of(); + } +} + +void main() {} diff --git a/proof/enterprise/JpaVsJakartaData.java b/proof/enterprise/JpaVsJakartaData.java new file mode 100755 index 0000000..dd9b385 --- /dev/null +++ b/proof/enterprise/JpaVsJakartaData.java @@ -0,0 +1,19 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS jakarta.data:jakarta.data-api:1.0.1 + +import jakarta.data.repository.*; +import java.util.*; + +/// Proof: jpa-vs-jakarta-data +/// Source: content/enterprise/jpa-vs-jakarta-data.yaml +class User { + Long id; String name; +} + +@Repository +interface Users extends CrudRepository { + List findByName(String name); +} + +void main() {} diff --git a/proof/enterprise/JsfManagedBeanVsCdiNamed.java b/proof/enterprise/JsfManagedBeanVsCdiNamed.java new file mode 100755 index 0000000..000ec1a --- /dev/null +++ b/proof/enterprise/JsfManagedBeanVsCdiNamed.java @@ -0,0 +1,30 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS jakarta.enterprise:jakarta.enterprise.cdi-api:4.1.0 + +import jakarta.enterprise.context.SessionScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import java.io.*; + +/// Proof: jsf-managed-bean-vs-cdi-named +/// Source: content/enterprise/jsf-managed-bean-vs-cdi-named.yaml +interface UserService { + String findName(String id); +} + +@Named +@SessionScoped +class UserBean implements Serializable { + @Inject + private UserService userService; + + private String name; + + public String getName() { return name; } + public void setName(String name) { + this.name = name; + } +} + +void main() {} diff --git a/proof/enterprise/ManualTransactionVsDeclarative.java b/proof/enterprise/ManualTransactionVsDeclarative.java new file mode 100755 index 0000000..bdb3142 --- /dev/null +++ b/proof/enterprise/ManualTransactionVsDeclarative.java @@ -0,0 +1,35 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS jakarta.enterprise:jakarta.enterprise.cdi-api:4.1.0 +//DEPS jakarta.persistence:jakarta.persistence-api:3.2.0 +//DEPS jakarta.transaction:jakarta.transaction-api:2.0.1 + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.persistence.*; +import jakarta.transaction.Transactional; +import java.math.*; + +/// Proof: manual-transaction-vs-declarative +/// Source: content/enterprise/manual-transaction-vs-declarative.yaml +class Account { + Long id; BigDecimal balance; + Account debit(BigDecimal amount) { return this; } + Account credit(BigDecimal amount) { return this; } +} + +@ApplicationScoped +class AccountService { + @PersistenceContext + EntityManager em; + + @Transactional + public void transferFunds(Long from, Long to, + BigDecimal amount) { + var src = em.find(Account.class, from); + var dst = em.find(Account.class, to); + src.debit(amount); + dst.credit(amount); + } +} + +void main() {} diff --git a/proof/enterprise/MdbVsReactiveMessaging.java b/proof/enterprise/MdbVsReactiveMessaging.java new file mode 100755 index 0000000..cf74c2e --- /dev/null +++ b/proof/enterprise/MdbVsReactiveMessaging.java @@ -0,0 +1,25 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS jakarta.enterprise:jakarta.enterprise.cdi-api:4.1.0 +//DEPS org.eclipse.microprofile.reactive.messaging:microprofile-reactive-messaging-api:3.0.1 + +import jakarta.enterprise.context.ApplicationScoped; +import org.eclipse.microprofile.reactive.messaging.Incoming; + +/// Proof: mdb-vs-reactive-messaging +/// Source: content/enterprise/mdb-vs-reactive-messaging.yaml +record Order(String id) {} + +void fulfillOrder(Order order) {} + +@ApplicationScoped +class OrderProcessor { + @Incoming("orders") + public void process(Order order) { + // automatically deserialized from + // the "orders" channel + fulfillOrder(order); + } +} + +void main() {} diff --git a/proof/enterprise/ServletVsJaxrs.java b/proof/enterprise/ServletVsJaxrs.java new file mode 100755 index 0000000..1183bbb --- /dev/null +++ b/proof/enterprise/ServletVsJaxrs.java @@ -0,0 +1,22 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS jakarta.ws.rs:jakarta.ws.rs-api:4.0.0 + +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.*; + +/// Proof: servlet-vs-jaxrs +/// Source: content/enterprise/servlet-vs-jaxrs.yaml +record User(String id) {} + +@Path("/users") +class UserResource { + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response getUser( + @QueryParam("id") String id) { + return Response.ok(new User(id)).build(); + } +} + +void main() {} diff --git a/proof/enterprise/SingletonEjbVsCdiApplicationScoped.java b/proof/enterprise/SingletonEjbVsCdiApplicationScoped.java new file mode 100755 index 0000000..cfd1b85 --- /dev/null +++ b/proof/enterprise/SingletonEjbVsCdiApplicationScoped.java @@ -0,0 +1,34 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS jakarta.enterprise:jakarta.enterprise.cdi-api:4.1.0 +//DEPS jakarta.annotation:jakarta.annotation-api:3.0.0 + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.annotation.PostConstruct; +import java.util.*; + +/// Proof: singleton-ejb-vs-cdi-application-scoped +/// Source: content/enterprise/singleton-ejb-vs-cdi-application-scoped.yaml +@ApplicationScoped +class ConfigCache { + private volatile Map cache; + + @PostConstruct + public void load() { + cache = loadFromDatabase(); + } + + public String get(String key) { + return cache.get(key); + } + + public void refresh() { + cache = loadFromDatabase(); + } + + private Map loadFromDatabase() { + return Map.of("key", "value"); + } +} + +void main() {} diff --git a/proof/enterprise/SoapVsJakartaRest.java b/proof/enterprise/SoapVsJakartaRest.java new file mode 100755 index 0000000..ba0a5c4 --- /dev/null +++ b/proof/enterprise/SoapVsJakartaRest.java @@ -0,0 +1,34 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS jakarta.ws.rs:jakarta.ws.rs-api:4.0.0 +//DEPS jakarta.inject:jakarta.inject-api:2.0.1 + +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.*; +import jakarta.inject.Inject; + +/// Proof: soap-vs-jakarta-rest +/// Source: content/enterprise/soap-vs-jakarta-rest.yaml +class User { + String id; String name; + User(String id, String name) { this.id = id; this.name = name; } +} + +interface UserService { + User findById(String id); +} + +@Path("/users") +@Produces(MediaType.APPLICATION_JSON) +class UserResource { + @Inject + UserService userService; + + @GET + @Path("/{id}") + public User getUser(@PathParam("id") String id) { + return userService.findById(id); + } +} + +void main() {} diff --git a/proof/enterprise/SpringApiVersioning.java b/proof/enterprise/SpringApiVersioning.java new file mode 100755 index 0000000..08b5634 --- /dev/null +++ b/proof/enterprise/SpringApiVersioning.java @@ -0,0 +1,46 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS org.springframework:spring-webmvc:7.0.5 + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.config.annotation.*; + +/// Proof: spring-api-versioning +/// Source: content/enterprise/spring-api-versioning.yaml +record ProductDtoV1(Long id) {} +record ProductDtoV2(Long id, String name) {} + +// Configure versioning once +@Configuration +class WebConfig implements WebMvcConfigurer { + @Override + public void configureApiVersioning( + ApiVersionConfigurer config) { + config.useRequestHeader("X-API-Version"); + } +} + +interface ProductService { + ProductDtoV1 getV1(Long id); + ProductDtoV2 getV2(Long id); +} + +// Single controller, version per method +@RestController +@RequestMapping("/api/products") +class ProductController { + ProductService service; + + @GetMapping(value = "/{id}", version = "1") + public ProductDtoV1 getV1(@PathVariable Long id) { + return service.getV1(id); + } + + @GetMapping(value = "/{id}", version = "2") + public ProductDtoV2 getV2(@PathVariable Long id) { + return service.getV2(id); + } +} + +void main() {} diff --git a/proof/enterprise/SpringNullSafetyJspecify.java b/proof/enterprise/SpringNullSafetyJspecify.java new file mode 100755 index 0000000..77c602b --- /dev/null +++ b/proof/enterprise/SpringNullSafetyJspecify.java @@ -0,0 +1,36 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS org.jspecify:jspecify:1.0.0 + +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; +import java.util.*; + +/// Proof: spring-null-safety-jspecify +/// Source: content/enterprise/spring-null-safety-jspecify.yaml +record User(String name) {} + +interface UserRepository { + Optional findById(String id); + List findAll(); + User save(User user); +} + +@NullMarked +class UserService { + UserRepository repository; + + public @Nullable User findById(String id) { + return repository.findById(id).orElse(null); + } + + public List findAll() { + return repository.findAll(); + } + + public User save(User user) { + return repository.save(user); + } +} + +void main() {} diff --git a/proof/enterprise/SpringXmlConfigVsAnnotations.java b/proof/enterprise/SpringXmlConfigVsAnnotations.java new file mode 100755 index 0000000..161bffd --- /dev/null +++ b/proof/enterprise/SpringXmlConfigVsAnnotations.java @@ -0,0 +1,41 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS org.springframework.boot:spring-boot-autoconfigure:3.4.3 +//DEPS org.springframework.boot:spring-boot:3.4.3 +//DEPS org.springframework:spring-context:7.0.5 +//DEPS org.springframework:spring-jdbc:7.0.5 + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.stereotype.Repository; +import org.springframework.stereotype.Service; +import org.springframework.jdbc.core.JdbcTemplate; + +/// Proof: spring-xml-config-vs-annotations +/// Source: content/enterprise/spring-xml-config-vs-annotations.yaml +@SpringBootApplication +class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} + +@Repository +class UserRepository { + private final JdbcTemplate jdbc; + + public UserRepository(JdbcTemplate jdbc) { + this.jdbc = jdbc; + } +} + +@Service +class UserService { + private final UserRepository repository; + + public UserService(UserRepository repository) { + this.repository = repository; + } +} + +void main() {} diff --git a/proof/errors/MultiCatch.java b/proof/errors/MultiCatch.java new file mode 100755 index 0000000..cc8293d --- /dev/null +++ b/proof/errors/MultiCatch.java @@ -0,0 +1,20 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.io.*; +import java.sql.*; +import java.text.*; + +/// Proof: multi-catch +/// Source: content/errors/multi-catch.yaml +void process() throws IOException, SQLException, ParseException {} +void log(Exception e) { System.err.println(e); } + +void main() { + try { + process(); + } catch (IOException + | SQLException + | ParseException e) { + log(e); + } +} diff --git a/proof/errors/NullInSwitch.java b/proof/errors/NullInSwitch.java new file mode 100755 index 0000000..7d806f1 --- /dev/null +++ b/proof/errors/NullInSwitch.java @@ -0,0 +1,19 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: null-in-switch +/// Source: content/errors/null-in-switch.yaml +enum Status { ACTIVE, PAUSED, STOPPED } + +String describe(Status status) { + return switch (status) { + case null -> "unknown"; + case ACTIVE -> "active"; + case PAUSED -> "paused"; + default -> "other"; + }; +} + +void main() { + describe(null); + describe(Status.ACTIVE); +} diff --git a/proof/errors/OptionalChaining.java b/proof/errors/OptionalChaining.java new file mode 100755 index 0000000..b4de1a8 --- /dev/null +++ b/proof/errors/OptionalChaining.java @@ -0,0 +1,19 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; + +/// Proof: optional-chaining +/// Source: content/errors/optional-chaining.yaml +record Address(String city) {} +record User(Address address) {} + +Address address(User u) { return u.address(); } +String city(Address a) { return a.city(); } + +void main() { + User user = null; + String city = Optional.ofNullable(user) + .map(User::address) + .map(Address::city) + .orElse("Unknown"); +} diff --git a/proof/errors/OptionalOrelsethrow.java b/proof/errors/OptionalOrelsethrow.java new file mode 100755 index 0000000..260804b --- /dev/null +++ b/proof/errors/OptionalOrelsethrow.java @@ -0,0 +1,11 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; + +/// Proof: optional-orelsethrow +/// Source: content/errors/optional-orelsethrow.yaml +void main() { + Optional optional = Optional.of("value"); + // Clear intent: throws NoSuchElementException if empty + String value = optional.orElseThrow(); +} diff --git a/proof/errors/RecordBasedErrors.java b/proof/errors/RecordBasedErrors.java new file mode 100755 index 0000000..3f36ad8 --- /dev/null +++ b/proof/errors/RecordBasedErrors.java @@ -0,0 +1,19 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.time.*; + +/// Proof: record-based-errors +/// Source: content/errors/record-based-errors.yaml +public record ApiError( + int code, + String message, + Instant timestamp +) { + public ApiError(int code, String msg) { + this(code, msg, Instant.now()); + } +} + +void main() { + var err = new ApiError(404, "not found"); +} diff --git a/proof/errors/RequireNonnullElse.java b/proof/errors/RequireNonnullElse.java new file mode 100755 index 0000000..387721e --- /dev/null +++ b/proof/errors/RequireNonnullElse.java @@ -0,0 +1,13 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; + +/// Proof: require-nonnull-else +/// Source: content/errors/require-nonnull-else.yaml +void main() { + String input = null; + String name = Objects + .requireNonNullElse( + input, "default" + ); +} diff --git a/proof/io/DeserializationFilters.java b/proof/io/DeserializationFilters.java new file mode 100755 index 0000000..1b9187f --- /dev/null +++ b/proof/io/DeserializationFilters.java @@ -0,0 +1,22 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.io.*; + +/// Proof: deserialization-filters +/// Source: content/io/deserialization-filters.yaml +void main() throws Exception { + var baos = new ByteArrayOutputStream(); + try (var oos = new ObjectOutputStream(baos)) { + oos.writeObject("test"); + } + var bais = new ByteArrayInputStream(baos.toByteArray()); + var ois = new ObjectInputStream(bais); + + ObjectInputFilter filter = + ObjectInputFilter.Config + .createFilter( + "java.lang.*;!*" + ); + ois.setObjectInputFilter(filter); + Object obj = ois.readObject(); +} diff --git a/proof/io/FileMemoryMapping.java b/proof/io/FileMemoryMapping.java new file mode 100755 index 0000000..3634313 --- /dev/null +++ b/proof/io/FileMemoryMapping.java @@ -0,0 +1,26 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.io.*; +import java.nio.*; +import java.nio.channels.*; +import java.nio.file.*; +import java.lang.foreign.*; + +/// Proof: file-memory-mapping +/// Source: content/io/file-memory-mapping.yaml +void main() throws Exception { + var path = Path.of(System.getProperty("java.io.tmpdir"), "proof-mmap.dat"); + Files.write(path, new byte[1024]); + FileChannel channel = + FileChannel.open(path, + StandardOpenOption.READ, + StandardOpenOption.WRITE); + try (Arena arena = Arena.ofShared()) { + MemorySegment segment = + channel.map( + FileChannel.MapMode.READ_WRITE, + 0, channel.size(), arena); + // No size limit + // ... + } // Deterministic cleanup +} diff --git a/proof/io/FilesMismatch.java b/proof/io/FilesMismatch.java new file mode 100755 index 0000000..c518d11 --- /dev/null +++ b/proof/io/FilesMismatch.java @@ -0,0 +1,15 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.nio.file.*; + +/// Proof: files-mismatch +/// Source: content/io/files-mismatch.yaml +void main() throws Exception { + var path1 = Path.of(System.getProperty("java.io.tmpdir"), "proof-a.txt"); + var path2 = Path.of(System.getProperty("java.io.tmpdir"), "proof-b.txt"); + Files.writeString(path1, "hello"); + Files.writeString(path2, "hello"); + long pos = Files.mismatch(path1, path2); + // -1 if identical + // otherwise: position of first difference +} diff --git a/proof/io/HttpClient.java b/proof/io/HttpClient.java new file mode 100755 index 0000000..c46a436 --- /dev/null +++ b/proof/io/HttpClient.java @@ -0,0 +1,17 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.net.*; +import java.net.http.*; + +/// Proof: http-client +/// Source: content/io/http-client.yaml +void main() throws Exception { + var client = HttpClient.newHttpClient(); + var request = HttpRequest.newBuilder() + .uri(URI.create("https://api.com/data")) + .build(); + // Compilation proof — not executed + // var response = client.send( + // request, BodyHandlers.ofString()); + // String body = response.body(); +} diff --git a/proof/io/InputstreamTransferto.java b/proof/io/InputstreamTransferto.java new file mode 100755 index 0000000..d8290a7 --- /dev/null +++ b/proof/io/InputstreamTransferto.java @@ -0,0 +1,13 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.io.*; +import java.io.InputStream; +import java.io.OutputStream; + +/// Proof: inputstream-transferto +/// Source: content/io/inputstream-transferto.yaml +void main() throws Exception { + InputStream input = new java.io.ByteArrayInputStream("hello".getBytes()); + OutputStream output = new java.io.ByteArrayOutputStream(); + input.transferTo(output); +} diff --git a/proof/io/IoClassConsoleIo.java b/proof/io/IoClassConsoleIo.java new file mode 100755 index 0000000..aaa3a53 --- /dev/null +++ b/proof/io/IoClassConsoleIo.java @@ -0,0 +1,8 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: io-class-console-io +/// Source: content/io/io-class-console-io.yaml +void main() { + // IO.readln prompts for input; here we just prove the API compiles + IO.println("Hello, " + "world"); +} diff --git a/proof/io/PathOf.java b/proof/io/PathOf.java new file mode 100755 index 0000000..7faa9d8 --- /dev/null +++ b/proof/io/PathOf.java @@ -0,0 +1,10 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.nio.file.*; + +/// Proof: path-of +/// Source: content/io/path-of.yaml +void main() { + var path = Path.of("src", "main", + "java", "App.java"); +} diff --git a/proof/io/ReadingFiles.java b/proof/io/ReadingFiles.java new file mode 100755 index 0000000..bc7ee7e --- /dev/null +++ b/proof/io/ReadingFiles.java @@ -0,0 +1,12 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.nio.file.*; + +/// Proof: reading-files +/// Source: content/io/reading-files.yaml +void main() throws Exception { + var path = Path.of(System.getProperty("java.io.tmpdir"), "proof-read.txt"); + Files.writeString(path, "content"); + String content = + Files.readString(path); +} diff --git a/proof/io/TryWithResourcesEffectivelyFinal.java b/proof/io/TryWithResourcesEffectivelyFinal.java new file mode 100755 index 0000000..c3ab164 --- /dev/null +++ b/proof/io/TryWithResourcesEffectivelyFinal.java @@ -0,0 +1,21 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS com.h2database:h2:2.3.232 + +import java.sql.*; + +/// Proof: try-with-resources-effectively-final +/// Source: content/io/try-with-resources-effectively-final.yaml +void use(Connection conn) throws SQLException {} + +Connection getConnection() throws SQLException { + return DriverManager.getConnection("jdbc:h2:mem:"); +} + +void main() throws Exception { + Connection conn = getConnection(); + // Use existing variable directly + try (conn) { + use(conn); + } +} diff --git a/proof/io/WritingFiles.java b/proof/io/WritingFiles.java new file mode 100755 index 0000000..1827ed6 --- /dev/null +++ b/proof/io/WritingFiles.java @@ -0,0 +1,13 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.nio.file.*; + +/// Proof: writing-files +/// Source: content/io/writing-files.yaml +void main() throws Exception { + String content = "hello world"; + Files.writeString( + Path.of(System.getProperty("java.io.tmpdir"), "proof-write.txt"), + content + ); +} diff --git a/proof/language/CompactCanonicalConstructor.java b/proof/language/CompactCanonicalConstructor.java new file mode 100755 index 0000000..2e1dcac --- /dev/null +++ b/proof/language/CompactCanonicalConstructor.java @@ -0,0 +1,17 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; + +/// Proof: compact-canonical-constructor +/// Source: content/language/compact-canonical-constructor.yaml +public record Person(String name, List pets) { + // Compact constructor + public Person { + Objects.requireNonNull(name); + pets = List.copyOf(pets); + } +} + +void main() { + var p = new Person("Alice", List.of("cat", "dog")); +} diff --git a/proof/language/CompactSourceFiles.java b/proof/language/CompactSourceFiles.java new file mode 100755 index 0000000..8b1b502 --- /dev/null +++ b/proof/language/CompactSourceFiles.java @@ -0,0 +1,7 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: compact-source-files +/// Source: content/language/compact-source-files.yaml +void main() { + IO.println("Hello, World!"); +} diff --git a/proof/language/DefaultInterfaceMethods.java b/proof/language/DefaultInterfaceMethods.java new file mode 100755 index 0000000..937d2fa --- /dev/null +++ b/proof/language/DefaultInterfaceMethods.java @@ -0,0 +1,26 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: default-interface-methods +/// Source: content/language/default-interface-methods.yaml +import java.io.*; + +public interface Logger { + default void log(String msg) { + System.out.println( + timestamp() + ": " + msg); + } + String timestamp(); +} + +// Multiple interfaces allowed +public class FileLogger + implements Logger, Closeable { + public String timestamp() { + return java.time.Instant.now().toString(); + } + public void close() {} +} + +void main() { + new FileLogger().log("hello"); +} diff --git a/proof/language/DiamondOperator.java b/proof/language/DiamondOperator.java new file mode 100755 index 0000000..dcfbd3f --- /dev/null +++ b/proof/language/DiamondOperator.java @@ -0,0 +1,16 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; +import java.util.function.*; + +/// Proof: diamond-operator +/// Source: content/language/diamond-operator.yaml +void main() { + Map> map = + new HashMap<>(); + // Java 9: diamond with anonymous classes + Predicate p = + new Predicate<>() { + public boolean test(String s) { return !s.isEmpty(); } + }; +} diff --git a/proof/language/ExhaustiveSwitch.java b/proof/language/ExhaustiveSwitch.java new file mode 100755 index 0000000..f2849f5 --- /dev/null +++ b/proof/language/ExhaustiveSwitch.java @@ -0,0 +1,22 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: exhaustive-switch +/// Source: content/language/exhaustive-switch.yaml +sealed interface Shape permits Circle, Rect {} +record Circle(double r) implements Shape {} +record Rect(double w, double h) implements Shape {} + +// sealed Shape permits Circle, Rect +double area(Shape s) { + return switch (s) { + case Circle c -> + Math.PI * c.r() * c.r(); + case Rect r -> + r.w() * r.h(); + }; // no default needed! +} + +void main() { + area(new Circle(1)); + area(new Rect(2, 3)); +} diff --git a/proof/language/FlexibleConstructorBodies.java b/proof/language/FlexibleConstructorBodies.java new file mode 100755 index 0000000..5c0cef5 --- /dev/null +++ b/proof/language/FlexibleConstructorBodies.java @@ -0,0 +1,23 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: flexible-constructor-bodies +/// Source: content/language/flexible-constructor-bodies.yaml +class Shape { + final double width, height; + Shape(double width, double height) { + this.width = width; + this.height = height; + } +} + +class Square extends Shape { + Square(double side) { + if (side <= 0) + throw new IllegalArgumentException("bad"); + super(side, side); + } +} + +void main() { + new Square(5); +} diff --git a/proof/language/GuardedPatterns.java b/proof/language/GuardedPatterns.java new file mode 100755 index 0000000..633c362 --- /dev/null +++ b/proof/language/GuardedPatterns.java @@ -0,0 +1,24 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: guarded-patterns +/// Source: content/language/guarded-patterns.yaml +sealed interface Shape permits Circle, Other {} +record Circle(double radius) implements Shape {} +record Other() implements Shape {} + +String describe(Shape shape) { + return switch (shape) { + case Circle c + when c.radius() > 10 + -> "large circle"; + case Circle c + -> "small circle"; + default -> "not a circle"; + }; +} + +void main() { + describe(new Circle(5)); + describe(new Circle(15)); + describe(new Other()); +} diff --git a/proof/language/MarkdownJavadocComments.java b/proof/language/MarkdownJavadocComments.java new file mode 100755 index 0000000..cd64a41 --- /dev/null +++ b/proof/language/MarkdownJavadocComments.java @@ -0,0 +1,23 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: markdown-javadoc-comments +/// Source: content/language/markdown-javadoc-comments.yaml +record User(int id, String name) {} + +/// Returns the `User` with +/// the given ID. +/// +/// Example: +/// ```java +/// var user = findUser(123); +/// ``` +/// +/// @param id the user ID +/// @return the user +public User findUser(int id) { + return new User(id, "Alice"); +} + +void main() { + findUser(1); +} diff --git a/proof/language/ModuleImportDeclarations.java b/proof/language/ModuleImportDeclarations.java new file mode 100755 index 0000000..c45875c --- /dev/null +++ b/proof/language/ModuleImportDeclarations.java @@ -0,0 +1,12 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import module java.base; + +/// Proof: module-import-declarations +/// Source: content/language/module-import-declarations.yaml +void main() { + // All of java.util, java.io, java.nio + // etc. available in one line + var list = new ArrayList(); + list.add("hello"); +} diff --git a/proof/language/PatternMatchingInstanceof.java b/proof/language/PatternMatchingInstanceof.java new file mode 100755 index 0000000..32571b2 --- /dev/null +++ b/proof/language/PatternMatchingInstanceof.java @@ -0,0 +1,10 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: pattern-matching-instanceof +/// Source: content/language/pattern-matching-instanceof.yaml +void main() { + Object obj = "Hello, world!"; + if (obj instanceof String s) { + System.out.println(s.length()); + } +} diff --git a/proof/language/PatternMatchingSwitch.java b/proof/language/PatternMatchingSwitch.java new file mode 100755 index 0000000..ee7f4ae --- /dev/null +++ b/proof/language/PatternMatchingSwitch.java @@ -0,0 +1,18 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: pattern-matching-switch +/// Source: content/language/pattern-matching-switch.yaml +String format(Object obj) { + return switch (obj) { + case Integer i -> "int: " + i; + case Double d -> "double: " + d; + case String s -> "str: " + s; + default -> "unknown"; + }; +} + +void main() { + format(42); + format(3.14); + format("hi"); +} diff --git a/proof/language/PrimitiveTypesInPatterns.java b/proof/language/PrimitiveTypesInPatterns.java new file mode 100755 index 0000000..f40cf11 --- /dev/null +++ b/proof/language/PrimitiveTypesInPatterns.java @@ -0,0 +1,21 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//JAVAC_OPTIONS --enable-preview --release 25 +//JAVA_OPTIONS --enable-preview +/// Proof: primitive-types-in-patterns +/// Source: content/language/primitive-types-in-patterns.yaml +String classify(int code) { + return switch (code) { + case int c when c >= 200 + && c < 300 -> "success"; + case int c when c >= 400 + && c < 500 -> "client error"; + default -> "other"; + }; +} + +void main() { + classify(200); + classify(404); + classify(500); +} diff --git a/proof/language/PrivateInterfaceMethods.java b/proof/language/PrivateInterfaceMethods.java new file mode 100755 index 0000000..499d817 --- /dev/null +++ b/proof/language/PrivateInterfaceMethods.java @@ -0,0 +1,22 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: private-interface-methods +/// Source: content/language/private-interface-methods.yaml +interface Logger { + private String format(String lvl, String msg) { + return "[" + lvl + "] " + timestamp() + msg; + } + default void logInfo(String msg) { + System.out.println(format("INFO", msg)); + } + default void logWarn(String msg) { + System.out.println(format("WARN", msg)); + } + String timestamp(); +} + +void main() { + Logger l = () -> "now"; + l.logInfo("started"); + l.logWarn("careful"); +} diff --git a/proof/language/RecordPatterns.java b/proof/language/RecordPatterns.java new file mode 100755 index 0000000..d4e5cbf --- /dev/null +++ b/proof/language/RecordPatterns.java @@ -0,0 +1,12 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: record-patterns +/// Source: content/language/record-patterns.yaml +record Point(int x, int y) {} + +void main() { + Object obj = new Point(3, 4); + if (obj instanceof Point(int x, int y)) { + System.out.println(x + y); + } +} diff --git a/proof/language/RecordsForDataClasses.java b/proof/language/RecordsForDataClasses.java new file mode 100755 index 0000000..da5ae2a --- /dev/null +++ b/proof/language/RecordsForDataClasses.java @@ -0,0 +1,9 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: records-for-data-classes +/// Source: content/language/records-for-data-classes.yaml +public record Point(int x, int y) {} + +void main() { + var p = new Point(1, 2); +} diff --git a/proof/language/SealedClasses.java b/proof/language/SealedClasses.java new file mode 100755 index 0000000..d7bb804 --- /dev/null +++ b/proof/language/SealedClasses.java @@ -0,0 +1,14 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: sealed-classes +/// Source: content/language/sealed-classes.yaml +public sealed interface Shape + permits Circle, Rect {} +public record Circle(double r) + implements Shape {} +public record Rect(double w, double h) + implements Shape {} + +void main() { + Shape s = new Circle(5); +} diff --git a/proof/language/StaticMembersInInnerClasses.java b/proof/language/StaticMembersInInnerClasses.java new file mode 100755 index 0000000..92e2f18 --- /dev/null +++ b/proof/language/StaticMembersInInnerClasses.java @@ -0,0 +1,20 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: static-members-in-inner-classes +/// Source: content/language/static-members-in-inner-classes.yaml +class Library { + // Can be inner class with statics + class Book { + static int globalBookCount; + + Book() { + Book.globalBookCount++; + } + } +} + +void main() { + // Usage + var lib = new Library(); + var book = lib.new Book(); +} diff --git a/proof/language/StaticMethodsInInterfaces.java b/proof/language/StaticMethodsInInterfaces.java new file mode 100755 index 0000000..27ef855 --- /dev/null +++ b/proof/language/StaticMethodsInInterfaces.java @@ -0,0 +1,20 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: static-methods-in-interfaces +/// Source: content/language/static-methods-in-interfaces.yaml +public interface Validator { + boolean validate(String s); + + static boolean isBlank(String s) { + return s == null || + s.trim().isEmpty(); + } +} + +void main() { + String input = ""; + // Usage + if (Validator.isBlank(input)) { + System.out.println("blank"); + } +} diff --git a/proof/language/SwitchExpressions.java b/proof/language/SwitchExpressions.java new file mode 100755 index 0000000..e173a5e --- /dev/null +++ b/proof/language/SwitchExpressions.java @@ -0,0 +1,15 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: switch-expressions +/// Source: content/language/switch-expressions.yaml +enum Day { MONDAY, TUESDAY, WEDNESDAY, + THURSDAY, FRIDAY, SATURDAY, SUNDAY } + +void main() { + Day day = Day.MONDAY; + String msg = switch (day) { + case MONDAY -> "Start"; + case FRIDAY -> "End"; + default -> "Mid"; + }; +} diff --git a/proof/language/TextBlocksForMultilineStrings.java b/proof/language/TextBlocksForMultilineStrings.java new file mode 100755 index 0000000..27ad51c --- /dev/null +++ b/proof/language/TextBlocksForMultilineStrings.java @@ -0,0 +1,11 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: text-blocks-for-multiline-strings +/// Source: content/language/text-blocks-for-multiline-strings.yaml +void main() { + String json = """ + { + "name": "Duke", + "age": 30 + }"""; +} diff --git a/proof/language/TypeInferenceWithVar.java b/proof/language/TypeInferenceWithVar.java new file mode 100755 index 0000000..cfa1163 --- /dev/null +++ b/proof/language/TypeInferenceWithVar.java @@ -0,0 +1,12 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; + +/// Proof: type-inference-with-var +/// Source: content/language/type-inference-with-var.yaml +void main() { + var map = new HashMap>(); + for (var entry : map.entrySet()) { + // clean and readable + } +} diff --git a/proof/language/UnnamedVariables.java b/proof/language/UnnamedVariables.java new file mode 100755 index 0000000..6b46305 --- /dev/null +++ b/proof/language/UnnamedVariables.java @@ -0,0 +1,21 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; + +/// Proof: unnamed-variables +/// Source: content/language/unnamed-variables.yaml +void process(Object value) {} +void log(String msg) {} + +void main() { + String input = "123"; + Map map = Map.of("a", 1); + try { + Integer.parseInt(input); + } catch (Exception _) { + log("parse failed"); + } + map.forEach((_, value) -> { + process(value); + }); +} diff --git a/proof/security/KeyDerivationFunctions.java b/proof/security/KeyDerivationFunctions.java new file mode 100755 index 0000000..c93c604 --- /dev/null +++ b/proof/security/KeyDerivationFunctions.java @@ -0,0 +1,23 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import javax.crypto.*; +import javax.crypto.spec.*; +import java.security.*; + +/// Proof: key-derivation-functions +/// Source: content/security/key-derivation-functions.yaml +void main() throws Exception { + var kdf = KDF.getInstance("HKDF-SHA256"); + byte[] inputKeyBytes = new byte[32]; + byte[] salt = new byte[16]; + byte[] info = "context".getBytes(); + var inputKey = new SecretKeySpec(inputKeyBytes, "HKDF"); + SecretKey key = kdf.deriveKey( + "AES", + HKDFParameterSpec + .ofExtract() + .addIKM(inputKey) + .addSalt(salt) + .thenExpand(info, 32) + ); +} diff --git a/proof/security/PemEncoding.java b/proof/security/PemEncoding.java new file mode 100755 index 0000000..d7d2459 --- /dev/null +++ b/proof/security/PemEncoding.java @@ -0,0 +1,20 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//JAVAC_OPTIONS --enable-preview --release 25 +//JAVA_OPTIONS --enable-preview +import java.security.*; + +/// Proof: pem-encoding +/// Source: content/security/pem-encoding.yaml +void main() throws Exception { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); + kpg.initialize(2048); + KeyPair kp = kpg.generateKeyPair(); + + // Encode to PEM + String pem = PEMEncoder.of() + .encodeToString(kp.getPublic()); + // Decode from PEM + var cert = PEMDecoder.of() + .decode(pem); +} diff --git a/proof/security/RandomGenerator.java b/proof/security/RandomGenerator.java new file mode 100755 index 0000000..b79adeb --- /dev/null +++ b/proof/security/RandomGenerator.java @@ -0,0 +1,15 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.random.*; + +/// Proof: random-generator +/// Source: content/security/random-generator.yaml +void main() { + // Algorithm-agnostic via factory + var rng = RandomGenerator.of("L64X128MixRandom"); + int value = rng.nextInt(100); + + // Or get a splittable generator + var rng2 = RandomGeneratorFactory + .of("L64X128MixRandom").create(); +} diff --git a/proof/security/StrongRandom.java b/proof/security/StrongRandom.java new file mode 100755 index 0000000..b2de0bb --- /dev/null +++ b/proof/security/StrongRandom.java @@ -0,0 +1,13 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.security.*; + +/// Proof: strong-random +/// Source: content/security/strong-random.yaml +void main() throws Exception { + // Platform's strongest algorithm + SecureRandom random = + SecureRandom.getInstanceStrong(); + byte[] bytes = new byte[32]; + random.nextBytes(bytes); +} diff --git a/proof/security/TlsDefault.java b/proof/security/TlsDefault.java new file mode 100755 index 0000000..58c72ae --- /dev/null +++ b/proof/security/TlsDefault.java @@ -0,0 +1,14 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.net.http.*; +import javax.net.ssl.*; + +/// Proof: tls-default +/// Source: content/security/tls-default.yaml +void main() throws Exception { + // TLS 1.3 is the default! + var client = HttpClient.newBuilder() + .sslContext(SSLContext.getDefault()) + .build(); + // Already using TLS 1.3 +} diff --git a/proof/streams/CollectorsFlatmapping.java b/proof/streams/CollectorsFlatmapping.java new file mode 100755 index 0000000..db7adc8 --- /dev/null +++ b/proof/streams/CollectorsFlatmapping.java @@ -0,0 +1,24 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; +import java.util.stream.*; +import static java.util.stream.Collectors.*; + +/// Proof: collectors-flatmapping +/// Source: content/streams/collectors-flatmapping.yaml +record Emp(String dept, List tags) {} + +void main() { + var employees = List.of( + new Emp("eng", List.of("java", "cloud")), + new Emp("eng", List.of("java", "ai")) + ); + var tagsByDept = employees.stream() + .collect(groupingBy( + Emp::dept, + flatMapping( + e -> e.tags().stream(), + toSet() + ) + )); +} diff --git a/proof/streams/OptionalIfpresentorelse.java b/proof/streams/OptionalIfpresentorelse.java new file mode 100755 index 0000000..2a5484e --- /dev/null +++ b/proof/streams/OptionalIfpresentorelse.java @@ -0,0 +1,22 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; + +/// Proof: optional-ifpresentorelse +/// Source: content/streams/optional-ifpresentorelse.yaml +record User(String name) {} + +Optional findUser(String id) { + return id.equals("known") ? Optional.of(new User("Alice")) : Optional.empty(); +} + +void greet(User u) { System.out.println("Hello " + u.name()); } +void handleMissing() { System.out.println("not found"); } + +void main() { + String id = "known"; + findUser(id).ifPresentOrElse( + this::greet, + this::handleMissing + ); +} diff --git a/proof/streams/OptionalOr.java b/proof/streams/OptionalOr.java new file mode 100755 index 0000000..6f722c3 --- /dev/null +++ b/proof/streams/OptionalOr.java @@ -0,0 +1,17 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; + +/// Proof: optional-or +/// Source: content/streams/optional-or.yaml +record Config(String value) {} + +Optional primary() { return Optional.empty(); } +Optional secondary() { return Optional.empty(); } +Optional defaults() { return Optional.of(new Config("default")); } + +void main() { + Optional cfg = primary() + .or(this::secondary) + .or(this::defaults); +} diff --git a/proof/streams/PredicateNot.java b/proof/streams/PredicateNot.java new file mode 100755 index 0000000..3ee7ad6 --- /dev/null +++ b/proof/streams/PredicateNot.java @@ -0,0 +1,13 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; +import java.util.function.*; + +/// Proof: predicate-not +/// Source: content/streams/predicate-not.yaml +void main() { + List list = List.of("hello", "", "world", " "); + List nonEmpty = list.stream() + .filter(Predicate.not(String::isBlank)) + .toList(); +} diff --git a/proof/streams/StreamGatherers.java b/proof/streams/StreamGatherers.java new file mode 100755 index 0000000..5874318 --- /dev/null +++ b/proof/streams/StreamGatherers.java @@ -0,0 +1,15 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; +import java.util.stream.*; + +/// Proof: stream-gatherers +/// Source: content/streams/stream-gatherers.yaml +void main() { + Stream stream = Stream.of(1, 2, 3, 4, 5); + var windows = stream + .gather( + Gatherers.windowSliding(3) + ) + .toList(); +} diff --git a/proof/streams/StreamIteratePredicate.java b/proof/streams/StreamIteratePredicate.java new file mode 100755 index 0000000..c445514 --- /dev/null +++ b/proof/streams/StreamIteratePredicate.java @@ -0,0 +1,14 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.stream.*; + +/// Proof: stream-iterate-predicate +/// Source: content/streams/stream-iterate-predicate.yaml +void main() { + Stream.iterate( + 1, + n -> n < 1000, + n -> n * 2 + ).forEach(System.out::println); + // stops when n >= 1000 +} diff --git a/proof/streams/StreamMapmulti.java b/proof/streams/StreamMapmulti.java new file mode 100755 index 0000000..724e3ea --- /dev/null +++ b/proof/streams/StreamMapmulti.java @@ -0,0 +1,24 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; +import java.util.stream.*; + +/// Proof: stream-mapmulti +/// Source: content/streams/stream-mapmulti.yaml +record Order(String id, List items) {} +record OrderItem(String orderId, String item) {} + +void main() { + var orders = List.of( + new Order("o1", List.of("a", "b")), + new Order("o2", List.of("c")) + ); + Stream stream = orders.stream(); + stream.mapMulti( + (order, downstream) -> { + for (var item : order.items()) + downstream.accept( + new OrderItem(order.id(), item)); + } + ).toList(); +} diff --git a/proof/streams/StreamOfNullable.java b/proof/streams/StreamOfNullable.java new file mode 100755 index 0000000..b47a2ef --- /dev/null +++ b/proof/streams/StreamOfNullable.java @@ -0,0 +1,11 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.stream.*; + +/// Proof: stream-of-nullable +/// Source: content/streams/stream-of-nullable.yaml +void main() { + String val = null; + Stream s = + Stream.ofNullable(val); +} diff --git a/proof/streams/StreamTakewhileDropwhile.java b/proof/streams/StreamTakewhileDropwhile.java new file mode 100755 index 0000000..e9f9ee2 --- /dev/null +++ b/proof/streams/StreamTakewhileDropwhile.java @@ -0,0 +1,14 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; +import java.util.stream.*; + +/// Proof: stream-takewhile-dropwhile +/// Source: content/streams/stream-takewhile-dropwhile.yaml +void main() { + List sorted = List.of(1, 5, 50, 100, 150, 200); + var result = sorted.stream() + .takeWhile(n -> n < 100) + .toList(); + // or: .dropWhile(n -> n < 10) +} diff --git a/proof/streams/StreamTolist.java b/proof/streams/StreamTolist.java new file mode 100755 index 0000000..0554993 --- /dev/null +++ b/proof/streams/StreamTolist.java @@ -0,0 +1,12 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.stream.*; + +/// Proof: stream-tolist +/// Source: content/streams/stream-tolist.yaml +void main() { + Stream stream = Stream.of("hello", "hi", "world"); + List result = stream + .filter(s -> s.length() > 3) + .toList(); +} diff --git a/proof/streams/VirtualThreadExecutor.java b/proof/streams/VirtualThreadExecutor.java new file mode 100755 index 0000000..2bd7d86 --- /dev/null +++ b/proof/streams/VirtualThreadExecutor.java @@ -0,0 +1,18 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.util.*; +import java.util.concurrent.*; + +/// Proof: virtual-thread-executor +/// Source: content/streams/virtual-thread-executor.yaml +interface Task { String run() throws Exception; } + +void main() throws Exception { + List tasks = List.of(() -> "result1", () -> "result2"); + try (var exec = Executors + .newVirtualThreadPerTaskExecutor()) { + var futures = tasks.stream() + .map(t -> exec.submit(t::run)) + .toList(); + } +} diff --git a/proof/strings/StringCharsStream.java b/proof/strings/StringCharsStream.java new file mode 100755 index 0000000..5e410ce --- /dev/null +++ b/proof/strings/StringCharsStream.java @@ -0,0 +1,12 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: string-chars-stream +/// Source: content/strings/string-chars-stream.yaml +void process(char c) {} + +void main() { + String str = "abc123"; + str.chars() + .filter(Character::isDigit) + .forEach(c -> process((char) c)); +} diff --git a/proof/strings/StringFormatted.java b/proof/strings/StringFormatted.java new file mode 100755 index 0000000..3a1bbbe --- /dev/null +++ b/proof/strings/StringFormatted.java @@ -0,0 +1,11 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: string-formatted +/// Source: content/strings/string-formatted.yaml +void main() { + String name = "Alice"; + int age = 30; + String msg = + "Hello %s, you are %d" + .formatted(name, age); +} diff --git a/proof/strings/StringIndentTransform.java b/proof/strings/StringIndentTransform.java new file mode 100755 index 0000000..9710f2d --- /dev/null +++ b/proof/strings/StringIndentTransform.java @@ -0,0 +1,12 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: string-indent-transform +/// Source: content/strings/string-indent-transform.yaml +void main() { + String text = "hello world"; + String indented = text.indent(4); + + String result = text + .transform(String::strip) + .transform(s -> s.replace(" ", "-")); +} diff --git a/proof/strings/StringIsblank.java b/proof/strings/StringIsblank.java new file mode 100755 index 0000000..3956702 --- /dev/null +++ b/proof/strings/StringIsblank.java @@ -0,0 +1,9 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: string-isblank +/// Source: content/strings/string-isblank.yaml +void main() { + String str = " \t "; + boolean blank = str.isBlank(); + // handles Unicode whitespace too +} diff --git a/proof/strings/StringLines.java b/proof/strings/StringLines.java new file mode 100755 index 0000000..3a078b0 --- /dev/null +++ b/proof/strings/StringLines.java @@ -0,0 +1,8 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: string-lines +/// Source: content/strings/string-lines.yaml +void main() { + String text = "one\ntwo\nthree"; + text.lines().forEach(System.out::println); +} diff --git a/proof/strings/StringRepeat.java b/proof/strings/StringRepeat.java new file mode 100755 index 0000000..579005b --- /dev/null +++ b/proof/strings/StringRepeat.java @@ -0,0 +1,8 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: string-repeat +/// Source: content/strings/string-repeat.yaml +void main() { + String result = "abc".repeat(3); + // "abcabcabc" +} diff --git a/proof/strings/StringStrip.java b/proof/strings/StringStrip.java new file mode 100755 index 0000000..7b1eb9a --- /dev/null +++ b/proof/strings/StringStrip.java @@ -0,0 +1,11 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +/// Proof: string-strip +/// Source: content/strings/string-strip.yaml +void main() { + String str = " hello world "; + // strip() removes all Unicode whitespace + String clean = str.strip(); + String left = str.stripLeading(); + String right = str.stripTrailing(); +} diff --git a/proof/tooling/BuiltInHttpServer.java b/proof/tooling/BuiltInHttpServer.java new file mode 100755 index 0000000..0b62480 --- /dev/null +++ b/proof/tooling/BuiltInHttpServer.java @@ -0,0 +1,16 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +import java.net.*; +import java.nio.file.*; +import com.sun.net.httpserver.*; + +/// Proof: built-in-http-server +/// Source: content/tooling/built-in-http-server.yaml +void main() throws Exception { + // Or use the API (JDK 18+) + var server = SimpleFileServer.createFileServer( + new InetSocketAddress(0), + Path.of(System.getProperty("java.io.tmpdir")).toAbsolutePath(), + SimpleFileServer.OutputLevel.VERBOSE); + // server.start(); // not started in proof +} diff --git a/proof/tooling/Junit6WithJspecify.java b/proof/tooling/Junit6WithJspecify.java new file mode 100755 index 0000000..cccfb1d --- /dev/null +++ b/proof/tooling/Junit6WithJspecify.java @@ -0,0 +1,44 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//JAVA 25+ +//DEPS org.junit.jupiter:junit-jupiter-api:6.0.3 +//DEPS org.jspecify:jspecify:1.0.0 + +import org.junit.jupiter.api.Test; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; +import static org.junit.jupiter.api.Assertions.*; + +/// Proof: junit6-with-jspecify +/// Source: content/tooling/junit6-with-jspecify.yaml +record User(String name) {} + +interface UserService { + @Nullable User findById(String id); +} + +UserService service = id -> id.equals("u1") ? new User("Alice") : null; + +@NullMarked // all refs non-null unless @Nullable +class UserServiceTest { + + // JUnit 6 API is @NullMarked: + // assertNull(@Nullable Object actual) + // assertEquals(@Nullable Object, @Nullable Object) + // fail(@Nullable String message) + + @Test + void findUser_found() { + // IDE warns: findById returns @Nullable User + @Nullable User result = service.findById("u1"); + assertNotNull(result); // narrows type to non-null + assertEquals("Alice", result.name()); // safe + } + + @Test + void findUser_notFound() { + @Nullable User result = service.findById("missing"); + assertNull(result); // IDE confirms null expectation + } +} + +void main() {}