)
+```
+
+#### Inspector
+
+Sanic ships with an optional Inspector, which is a special process that allows for the CLI to inspect the running state of an application and issue commands. It currently will only work if the CLI is being run on the same machine as the Sanic instance.
+
+```
+sanic path.to:app --inspect
+```
+
+
+
+The new CLI commands are:
+
+```
+ --inspect Inspect the state of a running instance, human readable
+ --inspect-raw Inspect the state of a running instance, JSON output
+ --trigger-reload Trigger worker processes to reload
+ --trigger-shutdown Trigger all processes to shutdown
+```
+
+This is not enabled by default. In order to have it available, you must opt in:
+
+```python
+app.config.INSPECTOR = True
+```
+
+*Note: [Sanic Extensions]() provides a [custom request](../basics/app.md#custom-requests) class that will add a request counter to the server state.
+
+#### Application multiplexer
+
+Many of the same information and functionality is available on the application instance itself. There is a new `multiplexer` object on the application instance that has the ability to restart one or more workers, and fetch information about the current state.
+
+You can access it as `app.multiplexer`, or more likely by its short alias `app.m`.
+
+```python
+@app.on_request
+async def print_state(request: Request):
+ print(request.app.m.state)
+```
+
+#### Potential upgrade issues
+
+Because of the switch from `fork` to `spawn`, if you try running the server in the global scope you will receive an error. If you see something like this:
+
+```
+sanic.exceptions.ServerError: Sanic server could not start: [Errno 98] Address already in use.
+This may have happened if you are running Sanic in the global scope and not inside of a `if __name__ == "__main__"` block.
+```
+
+... then the change is simple. Make sure `app.run` is inside a block.
+
+```python
+if __name__ == "__main__":
+ app.run(port=9999, dev=True)
+```
+
+#### Opting out of the new functionality
+
+If you would like to run Sanic without the new process manager, you may easily use the legacy runners. Please note that support for them **will be removed** in the future. A date has not yet been set, but will likely be sometime in 2023.
+
+To opt out of the new server and use the legacy, choose the appropriate method depending upon how you run Sanic:
+
+---:1
+If you use the CLI...
+:--:1
+```
+sanic path.to:app --legacy
+```
+:---
+
+---:1
+If you use `app.run`...
+:--:1
+```
+app.run(..., legacy=True)
+```
+:---
+
+---:1
+If you `app.prepare`...
+:--:1
+```
+app.prepare(...)
+Sanic.serve_legacy()
+```
+:---
+
+Similarly, you can force Sanic to run in a single process. This however means there will not be any access to the auto-reloader.
+
+---:1
+If you use the CLI...
+:--:1
+```
+sanic path.to:app --single-process
+```
+:---
+
+---:1
+If you use `app.run`...
+:--:1
+```
+app.run(..., single_process=True)
+```
+:---
+
+---:1
+If you `app.prepare`...
+:--:1
+```
+app.prepare(...)
+Sanic.serve_single()
+```
+:---
+### Middleware priority
+
+Middleware is executed in an order based upon when it was defined. Request middleware are executed in sequence and response middleware in reverse. This could have an unfortunate impact if your ordering is strictly based upon import ordering with global variables for example.
+
+A new addition is to break-out of the strict construct and allow a priority to be assigned to a middleware. The higher the number for a middleware definition, the earlier in the sequence it will be executed. This applies to **both** request and response middleware.
+
+```python
+@app.on_request
+async def low_priority(_):
+ ...
+
+@app.on_request(priority=10)
+async def high_priority(_):
+ ...
+```
+
+In the above example, even though `low_priority` is defined first, `high_priority` will run first.
+
+### Custom `loads` function
+
+
+Sanic has supported the ability to add a [custom `dumps` function](https://sanic.readthedocs.io/en/stable/sanic/api/app.html#sanic.app.Sanic) when instantiating an app. The same functionality has been extended to `loads`, which will be used when deserializing.
+
+```python
+from json import loads
+
+Sanic("Test", loads=loads)
+```
+
+### Websocket objects are now iterable
+
+
+Rather than calling `recv` in a loop on a `Websocket` object, you can iterate on it in a `for` loop.
+
+
+```python
+from sanic import Request, Websocket
+
+@app.websocket("/ws")
+async def ws_echo_handler(request: Request, ws: Websocket):
+ async for msg in ws:
+ await ws.send(msg)
+```
+
+### Appropriately respond with 304 on static files
+
+When serving a static file, the Sanic server can respond appropriately to a request with `If-Modified-Since` using a `304` response instead of resending a file.
+
+### Two new signals to wrap handler execution
+
+Two new [signals](../advanced/signals.md) have been added that wrap the execution of a request handler.
+
+- `http.handler.before` - runs after request middleware but before the route handler
+- `http.handler.after` - runs after the route handler
+ - In *most* circumstances, this also means that it will run before response middleware. However, if you call `request.respond` from inside of a route handler, then your middleware will come first
+
+### New Request properties for HTTP method information
+
+The HTTP specification defines which HTTP methods are: safe, idempotent, and cacheable. New properties have been added that will respond with a boolean flag to help identify the request property based upon the method.
+
+```python
+request.is_safe
+request.is_idempotent
+request.is_cacheable
+```
+
+### 🚨 *BREAKING CHANGE* - Improved cancel request exception
+
+In prior version of Sanic, if a `CancelledError` was caught it could bubble up and cause the server to respond with a `503`. This is not always the desired outcome, and it prevented the usage of that error in other circumstances. As a result, Sanic will now use a subclass of `CancelledError` called: `RequestCancelled` for this functionality. It likely should have little impact unless you were explicitly relying upon the old behavior.
+
+
+For more details on the specifics of these properties, checkout the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods).
+
+### New deprecation warning filter
+
+You can control the level of deprecation warnings from Sanic using [standard library warning filter values](https://docs.python.org/3/library/warnings.html#the-warnings-filter). Default is `"once"`.
+
+```python
+app.config.DEPRECATION_FILTER = "ignore"
+```
+
+### Deprecations and Removals
+
+1. *DEPRECATED* - Duplicate route names have been deprecated and will be removed in v23.3
+1. *DEPRECATED* - Registering duplicate exception handlers has been deprecated and will be removed in v23.3
+1. *REMOVED* - `route.ctx` not set by Sanic, and is a blank object for users, therefore ...
+ - `route.ctx.ignore_body` >> `route.extra.ignore_body`
+ - `route.ctx.stream` >> `route.extra.stream`
+ - `route.ctx.hosts` >> `route.extra.hosts`
+ - `route.ctx.static` >> `route.extra.static`
+ - `route.ctx.error_format` >> `route.extra.error_format`
+ - `route.ctx.websocket` >> `route.extra.websocket`
+1. *REMOVED* - `app.debug` is READ-ONLY
+1. *REMOVED* - `app.is_running` removed
+1. *REMOVED* - `app.is_stopping` removed
+1. *REMOVED* - `Sanic._uvloop_setting` removed
+1. *REMOVED* - Prefixed environment variables will be ignored if not uppercase
+
+
+## Thank you
+
+Thank you to everyone that participated in this release: :clap:
+
+[@ahopkins](https://github.com/ahopkins)
+[@azimovMichael](https://github.com/azimovMichael)
+[@ChihweiLHBird](https://github.com/ChihweiLHBird)
+[@huntzhan](https://github.com/huntzhan)
+[@monosans](https://github.com/monosans)
+[@prryplatypus](https://github.com/prryplatypus)
+[@SaidBySolo](https://github.com/SaidBySolo)
+[@seemethere](https://github.com/seemethere)
+[@sjsadowski](https://github.com/sjsadowski)
+[@timgates42](https://github.com/timgates42)
+[@Tronic](https://github.com/Tronic)
+
+
+---
+
+If you enjoy the project, please consider contributing. Of course we love code contributions, but we also love contributions in any form. Consider writing some documentation, showing off use cases, joining conversations and making your voice known, and if you are able: [financial contributions](https://opencollective.com/sanic-org/).
diff --git a/src/ja/guide/release-notes/v23.3.md b/src/ja/guide/release-notes/v23.3.md
new file mode 100644
index 0000000000..a64025b5dd
--- /dev/null
+++ b/src/ja/guide/release-notes/v23.3.md
@@ -0,0 +1,384 @@
+# Version 23.3
+
+[[toc]]
+
+## Introduction
+
+This is the first release of the version 23 [release cycle](../../org/policies.md#release-schedule). As such contains some deprecations and hopefully some *small* breaking changes. If you run into any issues, please raise a concern on [GitHub](https://github.com/sanic-org/sanic/issues/new/choose).
+
+## What to know
+
+More details in the [Changelog](https://sanic.readthedocs.io/en/stable/sanic/changelog.html). Notable new or breaking features, and what to upgrade...
+
+### Nicer traceback formatting
+
+The SCO adopted two projects into the Sanic namespace on GitHub: [tracerite](https://github.com/sanic-org/tracerite) and [html5tagger](https://github.com/sanic-org/html5tagger). These projects team up to provide and incredible new error page with more details to help the debugging process.
+
+This is provided out of the box, and will adjust to display only relevant information whether in DEBUG more or PROD mode.
+
+---:1
+**Using PROD mode**
+
+:--:
+**Using DEBUG mode**
+
+:---
+
+Light and dark mode HTML pages are available and will be used implicitly.
+
+### Basic file browser on directories
+
+When serving a directory from a static handler, Sanic can be configured to show a basic file browser instead using `directory_view=True`.
+
+---:1
+```python
+app.static("/uploads/", "/path/to/dir/", directory_view=True)
+```
+:--:
+
+:---
+
+
+Light and dark mode HTML pages are available and will be used implicitly.
+
+### HTML templating with Python
+
+Because Sanic is using [html5tagger](https://github.com/sanic-org/html5tagger) under the hood to render the [new error pages](#nicer-traceback-formatting), you now have the package available to you to easily generate HTML pages in Python code:
+
+
+---:1
+```python
+from html5tagger import Document
+from sanic import Request, Sanic, html
+
+app = Sanic("TestApp")
+
+
+@app.get("/")
+async def handler(request: Request):
+ doc = Document("My Website")
+ doc.h1("Hello, world.")
+ with doc.table(id="data"):
+ doc.tr.th("First").th("Second").th("Third")
+ doc.tr.td(1).td(2).td(3)
+ doc.p(class_="text")("A paragraph with ")
+ doc.a(href="/files")("a link")(" and ").em("formatting")
+ return html(doc)
+```
+:--:
+```html
+
+
+My Website
+Hello, world.
+
+
+ | First
+ | Second
+ | Third
+ |
+ | 1
+ | 2
+ | 3
+ |
+
+ A paragraph with a link and formatting
+```
+:---
+
+### Auto-index serving is available on static handlers
+
+Sanic can now be configured to serve an index file when serving a static directory.
+
+```python
+app.static("/assets/", "/path/to/some/dir", index="index.html")
+```
+
+When using the above, requests to `http://example.com/assets/` will automatically serve the `index.html` file located in that directory.
+
+### Simpler CLI targets
+
+It is common practice for Sanic applications to use the variable `app` as the application instance. Because of this, the CLI application target (the second value of the `sanic` CLI command) now tries to infer the application instance based upon what the target is. If the target is a module that contains an `app` variable, it will use that.
+
+There are now four possible ways to launch a Sanic application from the CLI.
+
+#### 1. Application instance
+
+
+As normal, providing a path to a module and an application instance will work as expected.
+
+```sh
+sanic path.to.module:app # global app instance
+```
+
+#### 2. Application factory
+
+Previously, to serve the factory pattern, you would need to use the `--factory` flag. This can be omitted now.
+
+```sh
+sanic path.to.module:create_app # factory pattern
+```
+
+#### 3. Path to launch Sanic Simple Server
+
+Similarly, to launch the Sanic simple server (serve static directory), you previously needed to use the `--simple` flag. This can be omitted now, and instead simply provide the path to the directory.
+
+```sh
+sanic ./path/to/directory/ # simple serve
+```
+
+#### 4. Python module containing an `app` variable
+
+As stated above, if the target is a module that contains an `app` variable, it will use that (assuming that `app` variable is a `Sanic` instance).
+
+```sh
+sanic path.to.module # module with app instance
+```
+
+### More convenient methods for setting and deleting cookies
+
+The old cookie pattern was awkward and clunky. It didn't look like regular Python because of the "magic" going on under the hood.
+
+---:1
+😱 This is not intuitive and is confusing for newcomers.
+:--:
+```python
+response = text("There's a cookie up in this response")
+response.cookies["test"] = "It worked!"
+response.cookies["test"]["domain"] = ".yummy-yummy-cookie.com"
+response.cookies["test"]["httponly"] = True
+```
+:---
+
+There are now new methods (and completely overhauled `Cookie` and `CookieJar` objects) to make this process more convenient.
+
+---:1
+😌 Ahh... Much nicer.
+:--:
+```python
+response = text("There's a cookie up in this response")
+response.add_cookie(
+ "test",
+ "It worked!",
+ domain=".yummy-yummy-cookie.com",
+ httponly=True
+)
+```
+:---
+
+### Better cookie compatibility
+
+Sanic has added support for [cookie prefixes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#cookie_prefixes), making it seemless and easy to read and write cookies with the values.
+
+While setting the cookie...
+
+```py
+response.cookies.add_cookie("foo", "bar", host_prefix=True)
+```
+
+This will create the prefixed cookie: `__Host-foo`. However, when accessing the cookie on an incoming request, you can do so without knowing about the existence of the header.
+
+```py
+request.cookies.get("foo")
+```
+
+It should also be noted, cookies can be accessed as properties just like [headers](#access-any-header-as-a-property).
+
+```python
+request.cookies.foo
+```
+
+And, cookies are similar to the `request.args` and `request.form` objects in that multiple values can be retrieved using `getlist`.
+
+```py
+request.cookies.getlist("foo")
+```
+
+Also added is support for creating [partitioned cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#partitioned_cookie).
+
+```py
+response.cookies.add_cookie(. . ., partitioned=True)
+```
+
+### 🚨 *BREAKING CHANGE* - More consistent and powerful `SanicException`
+
+Sanic has for a while included the `SanicException` as a base class exception. This could be extended to add `status_code`, etc. [See more details](http://localhost:8080/en/guide/best-practices/exceptions.html).
+
+**NOW**, using all of the various exceptions has become easier. The commonly used exceptions can be imported directly from the root level module.
+
+```python
+from sanic import NotFound, Unauthorized, BadRequest, ServerError
+```
+
+In addition, all of these arguments are available as keyword arguments on every exception type:
+
+| argument | type | description |
+|--|--|--|
+| `quiet` | `bool` | Suppress the traceback from the logs |
+| `context` | `dict` | Additional information shown in error pages *always* |
+| `extra` | `dict` | Additional information shown in error pages in *DEBUG* mode |
+| `headers` | `dict` | Additional headers sent in the response |
+
+None of these are themselves new features. However, they are more consistent in how you can use them, thus creating a powerful way to control error responses directly.
+
+```py
+raise ServerError(headers={"foo": "bar"})
+```
+
+The part of this that is a breaking change is that some formerly positional arguments are now keyword only.
+
+You are encouraged to look at the specific implementations for each error in the [API documents](https://sanic.readthedocs.io/en/stable/sanic/api/exceptions.html#module-sanic.exceptions).
+
+### 🚨 *BREAKING CHANGE* - Refresh `Request.accept` functionality to be more performant and spec-compliant
+
+Parsing od the `Accept` headers into the `Request.accept` accessor has been improved. If you were using this property and relying upon its equality operation, this has changed. You should probably transition to using the `request.accept.match()` method.
+
+### Access any header as a property
+
+To simplify access to headers, you can access a raw (unparsed) version of the header as a property. The name of the header is the name of the property in all lowercase letters, and switching any hyphens (`-`) to underscores (`_`).
+
+For example:
+
+---:1
+```
+GET /foo/bar HTTP/1.1
+Host: localhost
+User-Agent: curl/7.88.1
+X-Request-ID: 123ABC
+```
+:--:
+```py
+request.headers.host
+request.headers.user_agent
+request.headers.x_request_id
+```
+:---
+
+### Consume `DELETE` body by default
+
+By default, the body of a `DELETE` request will now be consumed and read onto the `Request` object. This will make `body` available like on `POST`, `PUT`, and `PATCH` requests without any further action.
+
+### Custom `CertLoader` for direct control of creating `SSLContext`
+
+Sometimes you may want to create your own `SSLContext` object. To do this, you can create your own subclass of `CertLoader` that will generate your desired context object.
+
+```python
+from sanic.worker.loader import CertLoader
+
+
+class MyCertLoader(CertLoader):
+ def load(self, app: Sanic) -> SSLContext:
+ . . .
+
+
+app = Sanic(. . ., certloader_class=MyCertLoader)
+```
+
+### Deprecations and Removals
+
+1. *DEPRECATED* - Dict-style cookie setting
+1. *DEPRECATED* - Using existence of JSON data on the request for one factor in using JSON error formatter
+1. *REMOVED* - Remove deprecated `__blueprintname__` property
+1. *REMOVED* - duplicate route names
+1. *REMOVED* - duplicate exception handler definitions
+1. *REMOVED* - inspector CLI with flags
+1. *REMOVED* - legacy server (including `sanic.server.serve_single` and `sanic.server.serve_multiple`)
+1. *REMOVED* - serving directory with bytes string
+1. *REMOVED* - `Request.request_middleware_started`
+1. *REMOVED* - `Websocket.connection`
+
+
+#### Duplicated route names are no longer allowed
+
+In version 22.9, Sanic announced that v23.3 would deprecate allowing routes to be registered with duplicate names. If you see the following error, it is because of that change:
+
+> sanic.exceptions.ServerError: Duplicate route names detected: SomeApp.some_handler. You should rename one or more of them explicitly by using the `name` param, or changing the implicit name derived from the class and function name. For more details, please see https://sanic.dev/en/guide/release-notes/v23.3.html#duplicated-route-names-are-no-longer-allowed
+
+If you are seeing this, you should opt-in to using explicit names for your routes.
+
+---:1
+**BAD**
+```python
+app = Sanic("SomeApp")
+
+@app.get("/")
+@app.get("/foo")
+async def handler(request: Request):
+```
+:--:
+**GOOD**
+```python
+app = Sanic("SomeApp")
+
+@app.get("/", name="root")
+@app.get("/foo", name="foo")
+async def handler(request: Request):
+```
+:---
+
+#### Response cookies
+
+Response cookies act as a `dict` for compatibility purposes only. In version 24.3, all `dict` methods will be removed and response cookies will be objects only.
+
+Therefore, if you are using this pattern to set cookie properties, you will need to upgrade it before version 24.3.
+
+```python
+resp = HTTPResponse()
+resp.cookies["foo"] = "bar"
+resp.cookies["foo"]["httponly"] = True
+```
+
+Instead, you should be using the `add_cookie` method:
+
+
+```python
+resp = HTTPResponse()
+resp.add_cookie("foo", "bar", httponly=True)
+```
+
+#### Request cookies
+
+Sanic has added support for reading duplicated cookie keys to be more in compliance with RFC specifications. To retain backwards compatibility, accessing a cookie value using `__getitem__` will continue to work to fetch the first value sent. Therefore, in version 23.3 and prior versions this will be `True`.
+
+```python
+assert request.cookies["foo"] == "bar"
+assert request.cookies.get("foo") == "bar"
+```
+
+Version 23.3 added `getlist`
+
+```python
+assert request.cookies.getlist("foo") == ["bar"]
+```
+
+As stated above, the `get` and `getlist` methods are available similar to how they exist on other request properties (`request.args`, `request.form`, etc). Starting in v24.3, the `__getitem__` method for cookies will work exactly like those properties. This means that `__getitem__` will return a list of values.
+
+Therefore, if you are relying upon this functionality to return only one value, you should upgrade to the following pattern before v24.3.
+
+```python
+assert request.cookies["foo"] == ["bar"]
+assert request.cookies.get("foo") == "bar"
+assert request.cookies.getlist("foo") == ["bar"]
+```
+
+
+## Thank you
+
+Thank you to everyone that participated in this release: :clap:
+
+[@ahopkins](https://github.com/ahopkins)
+[@ChihweiLHBird](https://github.com/ChihweiLHBird)
+[@deounix](https://github.com/deounix)
+[@Kludex](https://github.com/Kludex)
+[@mbendiksen](https://github.com/mbendiksen)
+[@prryplatypus](https://github.com/prryplatypus)
+[@r0x0d](https://github.com/r0x0d)
+[@SaidBySolo](https://github.com/SaidBySolo)
+[@sjsadowski](https://github.com/sjsadowski)
+[@stricaud](https://github.com/stricaud)
+[@Tracyca209](https://github.com/Tracyca209)
+[@Tronic](https://github.com/Tronic)
+
+---
+
+If you enjoy the project, please consider contributing. Of course we love code contributions, but we also love contributions in any form. Consider writing some documentation, showing off use cases, joining conversations and making your voice known, and if you are able: [financial contributions](https://opencollective.com/sanic-org/).
diff --git a/src/ja/guide/release-notes/v23.6.md b/src/ja/guide/release-notes/v23.6.md
new file mode 100644
index 0000000000..0a5d9dec9e
--- /dev/null
+++ b/src/ja/guide/release-notes/v23.6.md
@@ -0,0 +1,194 @@
+# Version 23.6
+
+[[toc]]
+
+## Introduction
+
+This is the second release of the version 23 [release cycle](../../org/policies.md#release-schedule). If you run into any issues, please raise a concern on [GitHub](https://github.com/sanic-org/sanic/issues/new/choose).
+
+## What to know
+
+More details in the [Changelog](https://sanic.readthedocs.io/en/stable/sanic/changelog.html). Notable new or breaking features, and what to upgrade...
+
+### Remove Python 3.7 support
+
+Python 3.7 is due to reach its scheduled upstream end-of-life on 2023-06-27. Sanic is now dropping support for Python 3.7, and requires Python 3.8 or newer.
+
+See [#2777](https://github.com/sanic-org/sanic/pull/2777).
+
+### Resolve pypy compatibility issues
+
+A small patch was added to the `os` module to once again allow for Sanic to run with PyPy. This workaround replaces the missing `readlink` function (missing in PyPy `os` module) with the function `os.path.realpath`, which serves to the same purpose.
+
+See [#2782](https://github.com/sanic-org/sanic/pull/2782).
+
+### Add custom typing to config and ctx objects
+
+The `sanic.Sanic` and `sanic.Request` object have become generic types that will make it more convenient to have fully typed `config` and `ctx` objects.
+
+In the most simple form, the `Sanic` object is typed as:
+
+```python
+from sanic import Sanic
+app = Sanic("test")
+reveal_type(app) # N: Revealed type is "sanic.app.Sanic[sanic.config.Config, types.SimpleNamespace]"
+```
+
+::: tip Note
+It should be noted, there is *no* requirement to use the generic types. The default types are `sanic.config.Config` and `types.SimpleNamespace`. This new feature is just an option for those that want to use it and existing types of `app: Sanic` and `request: Request` should work just fine.
+:::
+
+Now it is possible to have a fully-type `app.config`, `app.ctx`, and `request.ctx` objects though generics. This allows for better integration with auto completion tools in IDEs improving the developer experience.
+
+```python
+from sanic import Request, Sanic
+from sanic.config import Config
+
+class CustomConfig(Config):
+ pass
+
+class Foo:
+ pass
+
+class RequestContext:
+ foo: Foo
+
+class CustomRequest(Request[Sanic[CustomConfig, Foo], RequestContext]):
+ @staticmethod
+ def make_context() -> RequestContext:
+ ctx = RequestContext()
+ ctx.foo = Foo()
+ return ctx
+
+app = Sanic(
+ "test", config=CustomConfig(), ctx=Foo(), request_class=CustomRequest
+)
+
+@app.get("/")
+async def handler(request: CustomRequest):
+ ...
+```
+
+As a side effect, now `request.ctx` is lazy initialized, which should reduce some overhead when the `request.ctx` is unused.
+
+One further change you may have noticed in the above snippet is the `make_context` method. This new method can be used by custom `Request` types to inject an object different from a `SimpleNamespace` similar to how Sanic has allowed custom application context objects for a while.
+
+For a more thorough discussion, see [custom typed application](../basics/app.md#custom-typed-application) and [custom typed request](../basics/app.md#custom-typed-request).
+
+
+See [#2785](https://github.com/sanic-org/sanic/pull/2785).
+
+### Universal exception signal
+
+A new exception signal added for **ALL** exceptions raised while the server is running: `"server.exception.reporting"`. This is a universal signal that will be emitted for any exception raised, and dispatched as its own task. This means that it will *not* block the request handler, and will *not* be affected by any middleware.
+
+This is useful for catching exceptions that may occur outside of the request handler (for example in signals, or in a background task), and it intended for use to create a consistent error handling experience for the user.
+
+```python
+from sanic.signals import Event
+
+@app.signal(Event.SERVER_LIFECYCLE_EXCEPTION)
+async def catch_any_exception(app: Sanic, exception: Exception):
+ app.ctx.my_error_reporter_utility.error(exception)
+```
+
+This pattern can be simplified with a new decorator `@app.report_exception`:
+
+```python
+@app.report_exception
+async def catch_any_exception(app: Sanic, exception: Exception):
+ print("Caught exception:", exception)
+```
+
+It should be pointed out that this happens in a background task and is **NOT** for manipulation of an error response. It is only for reporting, logging, or other purposes that should be triggered when an application error occurs.
+
+See [#2724](https://github.com/sanic-org/sanic/pull/2724) and [#2792](https://github.com/sanic-org/sanic/pull/2792).
+
+### Add name prefixing to BP groups
+
+Sanic had been raising a warning on duplicate route names for a while, and started to enforce route name uniqueness in [v23.3](https://sanic.dev/en/guide/release-notes/v23.3.html#deprecations-and-removals). This created a complication for blueprint composition.
+
+New name prefixing parameter for blueprints groups has been added to alleviate this issue. It allows nesting of blueprints and groups to make them composable.
+
+The addition is the new `name_prefix` parameter as shown in this snippet.
+
+```python
+bp1 = Blueprint("bp1", url_prefix="/bp1")
+bp2 = Blueprint("bp2", url_prefix="/bp2")
+
+bp1.add_route(lambda _: ..., "/", name="route1")
+bp2.add_route(lambda _: ..., "/", name="route2")
+
+group_a = Blueprint.group(
+ bp1, bp2, url_prefix="/group-a", name_prefix="group-a"
+)
+group_b = Blueprint.group(
+ bp1, bp2, url_prefix="/group-b", name_prefix="group-b"
+)
+
+app = Sanic("TestApp")
+app.blueprint(group_a)
+app.blueprint(group_b)
+```
+
+The routes built will be named as follows:
+- `TestApp.group-a_bp1.route1`
+- `TestApp.group-a_bp2.route2`
+- `TestApp.group-b_bp1.route1`
+- `TestApp.group-b_bp2.route2`
+
+See [#2727](https://github.com/sanic-org/sanic/pull/2727).
+
+### Add `request.client_ip`
+
+Sanic has introduced `request.client_ip`, a new accessor that provides client's IP address from both local and proxy data. It allows running the application directly on Internet or behind a proxy. This is equivalent to `request.remote_addr or request.ip`, providing the client IP regardless of how the application is deployed.
+
+See [#2790](https://github.com/sanic-org/sanic/pull/2790).
+
+### Increase of `KEEP_ALIVE_TIMEOUT` default to 120 seconds
+
+The default `KEEP_ALIVE_TIMEOUT` value changed from 5 seconds to 120 seconds. It is of course still configurable, but this change should improve performance on long latency connections, where reconnecting is expensive, and better fits typical user flow browsing pages with longer-than-5-second intervals.
+
+Sanic has historically used 5 second timeouts to quickly close idle connections. The chosen value of **120 seconds** is indeed larger than Nginx default of 75, and is the same value that Caddy server has by default.
+
+Related to [#2531](https://github.com/sanic-org/sanic/issues/2531) and
+[#2681](https://github.com/sanic-org/sanic/issues/2681).
+
+See [#2670](https://github.com/sanic-org/sanic/pull/2670).
+
+### Set multiprocessing start method early
+
+Due to how Python handles `multiprocessing`, it may be confusing to some users how to properly create synchronization primitives. This is due to how Sanic creates the `multiprocessing` context. This change sets the start method early so that any primitives created will properly attach to the correct context.
+
+For most users, this should not be noticeable or impactful. But, it should make creation of something like this easier and work as expected.
+
+```python
+from multiprocessing import Queue
+
+@app.main_process_start
+async def main_process_start(app):
+ app.shared_ctx.queue = Queue()
+```
+
+See [#2776](https://github.com/sanic-org/sanic/pull/2776).
+
+## Thank you
+
+Thank you to everyone that participated in this release: :clap:
+
+[@ahopkins](https://github.com/ahopkins)
+[@ChihweiLHBird](https://github.com/ChihweiLHBird)
+[@chuckds](https://github.com/chuckds)
+[@deounix](https://github.com/deounix)
+[@guacs](https://github.com/guacs)
+[@liamcoatman](https://github.com/liamcoatman)
+[@moshe742](https://github.com/moshe742)
+[@prryplatypus](https://github.com/prryplatypus)
+[@SaidBySolo](https://github.com/SaidBySolo)
+[@Thirumalai](https://github.com/Thirumalai)
+[@Tronic](https://github.com/Tronic)
+
+
+---
+
+If you enjoy the project, please consider contributing. Of course we love code contributions, but we also love contributions in any form. Consider writing some documentation, showing off use cases, joining conversations and making your voice known, and if you are able: [financial contributions](https://opencollective.com/sanic-org/).
diff --git a/src/ja/help.md b/src/ja/help.md
index 7ac86e30a7..4a4f200879 100644
--- a/src/ja/help.md
+++ b/src/ja/help.md
@@ -12,7 +12,7 @@ layout: BlankLayout
チャットや質問への迅速な回答に最も適した場所です。
-[Discordサーバー](https://discord.gg/FARQzAEMAA)の`#sanic-support`チャンネルへ
+[Discordサーバー](https://discord.gg/FARQzAEMAA)の`#sanic-support`チャンネルへ (もしくは、日本人であれば`#general-jp-🇯🇵`チャンネルも使えますよ!)
:--:1
diff --git a/src/ja/org/feature_requests.md b/src/ja/org/feature_requests.md
new file mode 100644
index 0000000000..5c57ea1f02
--- /dev/null
+++ b/src/ja/org/feature_requests.md
@@ -0,0 +1,9 @@
+# Feature Requests
+
+[Create new feature request](https://github.com/sanic-org/sanic/issues/new?assignees=&labels=feature+request&template=feature_request.md)
+
+To vote on a feature request, visit the [GitHub Issues](https://github.com/sanic-org/sanic/issues?q=is%3Aissue+is%3Aopen+label%3A%22feature+request%22%2CRFC+sort%3Areactions-%2B1-desc) and add a reaction
+
+---
+
+
diff --git a/src/ja/plugins/sanic-ext/configuration.md b/src/ja/plugins/sanic-ext/configuration.md
index f8719470b9..daf117e279 100644
--- a/src/ja/plugins/sanic-ext/configuration.md
+++ b/src/ja/plugins/sanic-ext/configuration.md
@@ -1,3 +1,251 @@
# 設定
-_ドキュメンテーションは2022年10月公開予定_
+Sanic Extensions can be configured in all of the same ways that [you can configure Sanic](../../guide/deployment/configuration.md). That makes configuring Sanic Extensions very easy.
+
+```python
+app = Sanic("MyApp")
+app.config.OAS_URL_PREFIX = "/apidocs"
+```
+
+However, there are a few more configuration options that should be considered.
+
+## Manual `extend`
+
+---:1
+Even though Sanic Extensions will automatically attach to your application, you can manually choose `extend`. When you do that, you can pass all of the configuration values as a keyword arguments (lowercase).
+:--:
+```python
+app = Sanic("MyApp")
+app.extend(oas_url_prefix="/apidocs")
+```
+:---
+
+---:1
+Or, alternatively they could be passed all at once as a single `dict`.
+:--:
+```python
+app = Sanic("MyApp")
+app.extend(config={"oas_url_prefix": "/apidocs"})
+```
+:---
+
+---:1
+Both of these solutions suffers from the fact that the names of the configuration settings are not discoverable by an IDE. Therefore, there is also a type annotated object that you can use. This should help the development experience.
+:--:
+```python
+from sanic_ext import Config
+
+app = Sanic("MyApp")
+app.extend(config=Config(oas_url_prefix="/apidocs"))
+```
+:---
+
+## Settings
+
+### `cors`
+
+- **Type**: `bool`
+- **Default**: `True`
+- **Description**: Whether to enable CORS protection
+
+### `cors_allow_headers`
+
+- **Type**: `str`
+- **Default**: `"*"`
+- **Description**: Value of the header: `access-control-allow-headers`
+
+### `cors_always_send`
+
+- **Type**: `bool`
+- **Default**: `True`
+- **Description**: Whether to always send the header: `access-control-allow-origin`
+
+### `cors_automatic_options`
+
+- **Type**: `bool`
+- **Default**: `True`
+- **Description**: Whether to automatically generate `OPTIONS` endpoints for routes that do *not* already have one defined
+
+### `cors_expose_headers`
+
+- **Type**: `str`
+- **Default**: `""`
+- **Description**: Value of the header: `access-control-expose-headers`
+
+### `cors_max_age`
+
+- **Type**: `int`
+- **Default**: `5`
+- **Description**: Value of the header: `access-control-max-age`
+
+### `cors_methods`
+
+- **Type**: `str`
+- **Default**: `""`
+- **Description**: Value of the header: `access-control-access-control-allow-methods`
+
+### `cors_origins`
+
+- **Type**: `str`
+- **Default**: `""`
+- **Description**: Value of the header: `access-control-allow-origin`
+
+::: warning
+Be very careful if you place `*` here. Do not do this unless you know what you are doing as it can be a security issue.
+:::
+
+### `cors_send_wildcard`
+
+- **Type**: `bool`
+- **Default**: `False`
+- **Description**: Whether to send a wildcard origin instead of the incoming request origin
+
+### `cors_supports_credentials`
+
+- **Type**: `bool`
+- **Default**: `False`
+- **Description**: Value of the header: `access-control-allow-credentials`
+
+### `cors_vary_header`
+
+- **Type**: `bool`
+- **Default**: `True`
+- **Description**: Whether to add the `vary` header
+
+### `http_all_methods`
+
+- **Type**: `bool`
+- **Default**: `True`
+- **Description**: Adds the HTTP `CONNECT` and `TRACE` methods as allowable
+
+### `http_auto_head`
+
+- **Type**: `bool`
+- **Default**: `True`
+- **Description**: Automatically adds `HEAD` handlers to any `GET` routes
+
+### `http_auto_options`
+
+- **Type**: `bool`
+- **Default**: `True`
+- **Description**: Automatically adds `OPTIONS` handlers to any routes without
+
+### `http_auto_trace`
+
+- **Type**: `bool`
+- **Default**: `False`
+- **Description**: Automatically adds `TRACE` handlers to any routes without
+
+### `oas`
+
+- **Type**: `bool`
+- **Default**: `True`
+- **Description**: Whether to enable OpenAPI specification generation
+
+### `oas_autodoc`
+
+- **Type**: `bool`
+- **Default**: `True`
+- **Description**: Whether to automatically extract OpenAPI details from the docstring of a route function
+
+### `oas_ignore_head`
+
+- **Type**: `bool`
+- **Default**: `True`
+- **Description**: WHen `True`, it will not add `HEAD` endpoints into the OpenAPI specification
+
+### `oas_ignore_options`
+
+- **Type**: `bool`
+- **Default**: `True`
+- **Description**: WHen `True`, it will not add `OPTIONS` endpoints into the OpenAPI specification
+
+### `oas_path_to_redoc_html`
+
+- **Type**: `Optional[str]`
+- **Default**: `None`
+- **Description**: Path to HTML file to override the existing Redoc HTML
+
+### `oas_path_to_swagger_html`
+
+- **Type**: `Optional[str]`
+- **Default**: `None`
+- **Description**: Path to HTML file to override the existing Swagger HTML
+
+### `oas_ui_default`
+
+- **Type**: `Optional[str]`
+- **Default**: `"redoc"`
+- **Description**: Which OAS documentation to serve on the bare `oas_url_prefix` endpoint; when `None` there will be no documentation at that location
+
+### `oas_ui_redoc`
+
+- **Type**: `bool`
+- **Default**: `True`
+- **Description**: Whether to enable the Redoc UI
+
+### `oas_ui_swagger`
+
+- **Type**: `bool`
+- **Default**: `True`
+- **Description**: Whether to enable the Swagger UI
+
+### `oas_ui_swagger_version`
+
+- **Type**: `str`
+- **Default**: `"4.1.0"`
+- **Description**: Which Swagger version to use
+
+### `oas_uri_to_config`
+
+- **Type**: `str`
+- **Default**: `"/swagger-config"`
+- **Description**: Path to serve the Swagger configurtaion
+
+### `oas_uri_to_json`
+
+- **Type**: `str`
+- **Default**: `"/openapi.json"`
+- **Description**: Path to serve the OpenAPI JSON
+
+### `oas_uri_to_redoc`
+
+- **Type**: `str`
+- **Default**: `"/redoc"`
+- **Description**: Path to Redoc
+
+### `oas_uri_to_swagger`
+
+- **Type**: `str`
+- **Default**: `"/swagger"`
+- **Description**: Path to Swagger
+
+### `oas_url_prefix`
+
+- **Type**: `str`
+- **Default**: `"/docs"`
+- **Description**: URL prefix for the Blueprint that all of the OAS documentation witll attach to
+
+### `swagger_ui_configuration`
+
+- **Type**: `Dict[str, Any]`
+- **Default**: `{"apisSorter": "alpha", "operationsSorter": "alpha", "docExpansion": "full"}`
+- **Description**: The Swagger documentation to be served to the frontend
+
+### `templating_enable_async`
+
+- **Type**: `bool`
+- **Default**: `True`
+- **Description**: Whether to set `enable_async` on the Jinja `Environment`
+
+### `templating_path_to_templates`
+
+- **Type**: `Union[str, os.PathLike, Sequence[Union[str, os.PathLike]]] `
+- **Default**: `templates`
+- **Description**: A single path, or multiple paths to where your template files are located
+
+### `trace_excluded_headers`
+
+- **Type**: `Sequence[str]`
+- **Default**: `("authorization", "cookie")`
+- **Description**: Which headers should be suppresed from responses to `TRACE` requests
diff --git a/src/ja/plugins/sanic-ext/convenience.md b/src/ja/plugins/sanic-ext/convenience.md
index 731343f4fe..99c7408036 100644
--- a/src/ja/plugins/sanic-ext/convenience.md
+++ b/src/ja/plugins/sanic-ext/convenience.md
@@ -3,11 +3,8 @@
## シリアライザーの修正
---:1
-
アプリケーションを開発していると、常に同じようなレスポンスを返すルートが存在することがよくあります。このような場合、エンドポイントで返されるシリアライザーをあらかじめ定義しておけば、あとはコンテンツを返すだけでよいのです。
-
:--:1
-
```python
from sanic_ext import serializer
@@ -18,15 +15,11 @@ async def hello_world(request, name: str):
return "hello " * int(name)
return f"Hello, {name}"
```
-
:---
-
---:1
-
`@serializer` デコレータは、ステータスコードを追加することもできます。
-
:--:1
```python
from sanic_ext import serializer
@@ -40,13 +33,9 @@ async def create_something(request):
## カスタムシリアライザー
-
---:1
-
`@serializer` デコレータを使用すると、有効な型 (`HTTPResonse`) を返す限りにおいて、独自のカスタム関数を渡すことも可能です。
-
:--:1
-
```python
def message(retval, request, action, status):
return json(
@@ -64,13 +53,10 @@ def message(retval, request, action, status):
async def do_action(request, action: str):
return "This is a message"
```
-
:---
---:1
-
さて、文字列だけを返すと、素敵なシリアル化された出力が返されるはずです。
-
:--:1
```python
@@ -82,5 +68,31 @@ $ curl localhost:8000/eat_cookies -X POST
}
```
+:---
+
+
+## Request counter
+
+---:1
+Sanic Extensions comes with a subclass of `Request` that can be setup to automatically keep track of the number of requests processed per worker process. To enable this, you should pass the `CountedRequest` class to your application contructor.
+:--:1
+```python
+from sanic_ext import CountedRequest
+
+app = Sanic(..., request_class=CountedRequest)
+```
+:---
+---:1
+You will now have access to the number of requests served during the lifetime of the worker process.
+:--:1
+```python
+@app.get("/")
+async def handler(request: CountedRequest):
+ return json({"count": request.count})
+```
:---
+
+If possible, the request count will also be added to the [worker state](../../guide/deployment/manager.md#worker-state).
+
+
diff --git a/src/ja/plugins/sanic-ext/custom.md b/src/ja/plugins/sanic-ext/custom.md
new file mode 100644
index 0000000000..ca712f183f
--- /dev/null
+++ b/src/ja/plugins/sanic-ext/custom.md
@@ -0,0 +1,86 @@
+# Custom extensions
+
+It is possible to create your own custom extensions.
+
+Version 22.9 added the `Extend.register` [method](#extension-preregistration). This makes it extremely easy to add custom expensions to an application.
+
+## Anatomy of an extension
+
+All extensions must subclass `Extension`.
+
+### Required
+
+- `name`: By convention, the name is an all-lowercase string
+- `startup`: A method that runs when the extension is added
+
+### Optional
+
+- `label`: A method that returns additional information about the extension in the MOTD
+- `included`: A method that returns a boolean whether the extension should be enabled or not (could be used for example to check config state)
+
+### Example
+
+```python
+from sanic import Request, Sanic, json
+from sanic_ext import Extend, Extension
+
+app = Sanic(__name__)
+app.config.MONITOR = True
+
+
+class AutoMonitor(Extension):
+ name = "automonitor"
+
+ def startup(self, bootstrap) -> None:
+ if self.included():
+ self.app.before_server_start(self.ensure_monitor_set)
+ self.app.on_request(self.monitor)
+
+ @staticmethod
+ async def monitor(request: Request):
+ if request.route and request.route.ctx.monitor:
+ print("....")
+
+ @staticmethod
+ async def ensure_monitor_set(app: Sanic):
+ for route in app.router.routes:
+ if not hasattr(route.ctx, "monitor"):
+ route.ctx.monitor = False
+
+ def label(self):
+ has_monitor = [
+ route
+ for route in self.app.router.routes
+ if getattr(route.ctx, "monitor", None)
+ ]
+ return f"{len(has_monitor)} endpoint(s)"
+
+ def included(self):
+ return self.app.config.MONITOR
+
+
+Extend.register(AutoMonitor)
+
+
+@app.get("/", ctx_monitor=True)
+async def handler(request: Request):
+ return json({"foo": "bar"})
+```
+
+
+## Extension preregistration
+
+---:1
+`Extend.register` simplifies the addition of custom extensions.
+:--:1
+```python
+from sanic_ext import Extend, Extension
+
+class MyCustomExtension(Extension):
+ ...
+
+Extend.register(MyCustomExtension())
+```
+:---
+
+*Added in v22.9*
diff --git a/src/ja/plugins/sanic-ext/getting-started.md b/src/ja/plugins/sanic-ext/getting-started.md
index ed42f5cdb3..a749f9d0ab 100644
--- a/src/ja/plugins/sanic-ext/getting-started.md
+++ b/src/ja/plugins/sanic-ext/getting-started.md
@@ -4,12 +4,13 @@ Sanic Extensionsは、SCOが開発し、保守している*公式サポート*
## 機能
-- 自動で`HEAD`、`OPTIONS`、`TRACE`エンドポイントを作成
- CORSによる保護
-- あらかじめ定義されたエンドポイント固有のレスポンスシリアライザー
+- Jinjaによるテンプレートのレンダリング
- ルートハンドラへの引数挿入
- RedocやSwaggerを使ったOpenAPIドキュメンテーション
+- あらかじめ定義されたエンドポイント固有のレスポンスシリアライザー
- リクエストのクエリ引数とボディ入力のバリデーション
+- 自動で`HEAD`、`OPTIONS`、`TRACE`エンドポイントを作成
## 最低要件
@@ -34,11 +35,10 @@ pip install sanic-ext
Sanic Extensionsは、特別な操作なしに、たくさんの機能を有効にしてくれます。
-::: new NEW in v21.12
---:1
Sanic Extensions (v21.12+) をセットアップするために必要なこと: **何もない**。環境にインストールされていれば、セットアップが完了し、すぐに使えるようになっています。
-このコードは、[Sanic Getting Started page](../../guide/getting-started.md) にある Hello, world アプリを変更せずにそのまま使用しています_。
+このコードは、[Sanic Getting Started page](../../guide/getting-started.md) にある Hello, world アプリ_変更せずにそのまま使用していますが_、バックグラウンドに`sanic-ext`をインストールしSanic Extensionsを利用しています。
:--:1
```python
from sanic import Sanic
@@ -50,15 +50,15 @@ app = Sanic("MyHelloWorldApp")
async def hello_world(request):
return text("Hello, world.")
```
+
:---
-:::
---:1
**古い非推奨の設定**
v21.9 では、`Extend` でインスタンス化するのが最も簡単な方法です。
-Sanic Getting Started page](../../guide/getting-started.md) の Hello, world アプリを見返してみると、ここで追加されているのはハイライトした2行だけであることがわかると思います。
+[Sanicを始めよう](../../guide/getting-started.md) ページの Hello, world アプリを見返してみると、ここで追加されているのはハイライトした2行だけであることがわかると思います。
:--:1
```python{3,6}
diff --git a/src/ja/plugins/sanic-ext/health-monitor.md b/src/ja/plugins/sanic-ext/health-monitor.md
new file mode 100644
index 0000000000..f311196884
--- /dev/null
+++ b/src/ja/plugins/sanic-ext/health-monitor.md
@@ -0,0 +1,65 @@
+# Health monitor
+
+The health monitor requires both `sanic>=22.9` and `sanic-ext>=22.9`.
+
+You can setup Sanic Extensions to monitor the health of your worker processes. This requires that you not be in [single process mode](../../guide/deployment/manager.md#single-process-mode).
+
+## Setup
+
+---:1
+Out of the box, the health monitor is disabled. You will need to opt-in if you would like to use it.
+:--:1
+```python
+app.config.HEALTH = True
+```
+:---
+
+## How does it work
+
+The monitor sets up a new background process that will periodically receive acknowledgements of liveliness from each worker process. If a worker process misses a report too many times, then the monitor will restart that one worker.
+
+## Diagnostics endpoint
+
+---:1
+The health monitor will also enable a diagnostics endpoint that outputs the [worker state](../../guide/deployment/manager.md#worker-state). By default is id disabled.
+
+::: warning
+The diagnostics endpoint is not secured. If you are deploying it in a production environment, you should take steps to protect it with a proxy server if you are using one. If not, you may want to consider disabling this feature in production since it will leak details about your server state.
+:::
+:--:1
+```
+$ curl http://localhost:8000/__health__
+{
+ 'Sanic-Main': {'pid': 99997},
+ 'Sanic-Server-0-0': {
+ 'server': True,
+ 'state': 'ACKED',
+ 'pid': 9999,
+ 'start_at': datetime.datetime(2022, 10, 1, 0, 0, 0, 0, tzinfo=datetime.timezone.utc),
+ 'starts': 2,
+ 'restart_at': datetime.datetime(2022, 10, 1, 0, 0, 12, 861332, tzinfo=datetime.timezone.utc)
+ },
+ 'Sanic-Reloader-0': {
+ 'server': False,
+ 'state': 'STARTED',
+ 'pid': 99998,
+ 'start_at': datetime.datetime(2022, 10, 1, 0, 0, 0, 0, tzinfo=datetime.timezone.utc),
+ 'starts': 1
+ }
+}
+```
+:---
+
+
+## Configuration
+
+| Key | Type | Default| Description |
+|--|--|--|--|
+| HEALTH | `bool` | `False` | Whether to enable this extension. |
+| HEALTH_ENDPOINT | `bool` | `False` | Whether to enable the diagnostics endpoint. |
+| HEALTH_MAX_MISSES | `int` | `3` | The number of consecutive misses before a worker process is restarted. |
+| HEALTH_MISSED_THRESHHOLD | `int` | `10` | The number of seconds the monitor checks for worker process health. |
+| HEALTH_MONITOR | `bool` | `True` | Whether to enable the health monitor. |
+| HEALTH_REPORT_INTERVAL | `int` | `5` | The number of seconds between reporting each acknowledgement of liveliness. |
+| HEALTH_URI_TO_INFO | `str` | `""` | The URI path of the diagnostics endpoint. |
+| HEALTH_URL_PREFIX | `str` | `"/__health__"` | The URI prefix of the diagnostics blueprint. |
diff --git a/src/ja/plugins/sanic-ext/http/methods.md b/src/ja/plugins/sanic-ext/http/methods.md
index f9d246c5e8..2a013715c8 100644
--- a/src/ja/plugins/sanic-ext/http/methods.md
+++ b/src/ja/plugins/sanic-ext/http/methods.md
@@ -9,7 +9,7 @@
:::tab HEAD
-- **Configuration**: `AUTO_HEAD` (default `True`)
+- **Configuration**: `AUTO_HEAD` (デフォルトは`True`)
- **MDN**: [Read more](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD)
`HEAD` リクエストはヘッダーを提供し、それ以外は `GET` リクエストが提供するものと同じレスポンスを提供します。
@@ -36,7 +36,7 @@ content-type: text/plain; charset=utf-8
:::tab OPTIONS
-- **Configuration**: `AUTO_OPTIONS` (default `True`)
+- **Configuration**: `AUTO_OPTIONS` (デフォルトは`True`)
- **MDN**: [Read more](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS)
`OPTIONS` リクエストは、クライアントが与えられたエンドポイントとの通信をどのように許可されるかの詳細を受信者に提供します。
@@ -81,7 +81,7 @@ async def handler(request):
```python
from sanic_ext import Extend, Config
-Extend(app, config=Config(auto_trace=True))
+app.extend(config=Config(http_auto_trace=True))
```
さて、いくつかのエンドポイントが設定されていると仮定して、以下のようにトレースすることができます。
diff --git a/src/ja/plugins/sanic-ext/injection.md b/src/ja/plugins/sanic-ext/injection.md
index 2de93dd596..5e68c9517c 100644
--- a/src/ja/plugins/sanic-ext/injection.md
+++ b/src/ja/plugins/sanic-ext/injection.md
@@ -30,11 +30,8 @@ v21.12より前に依存性インジェクションを使用していた場合
最も単純な使用例は、単に値を再キャストすることです。
---:1
-
これは、マッチしたパスパラメータに基づいて生成したいモデルがある場合に便利です。
-
:--:1
-
```python
@dataclass
class IceCream:
@@ -69,13 +66,10 @@ flavor = IceCream(flavor="chocolate")
## 追加コンストラクタ
---:1
-
時には、コンストラクタを渡す必要があるかもしれません。これは関数でもいいですし、クラスメソッドでコンストラクタとして動作させることもできます。この例では、最初に `Person.create` を呼び出すインジェクションを作成します。
また、この例で重要なのは、実際に**2個**のオブジェクトをインジェクションしていることです! もちろん、このようにする必要はありませんが、関数のサインに基づいてオブジェクトをインジェクトすることになります。
-
:--:1
-
```python
@dataclass
class PersonID:
@@ -113,14 +107,40 @@ Person(person_id=PersonID(person_id=123), name='noname', age=111)
この例のように `ext.add_dependency` に `constructor` が渡されると、それが呼び出されます。そうでない場合は、 `type` を呼び出してオブジェクトを生成します。`constructor`を渡す際に注意すべき点がいくつかある。
-1. `request: request` の位置専用引数が期待されます。例として、上記の `Person.create` メソッドを参照してください。
+1. A positional `request: Request` argument is *usually* expected. See the `Person.create` method above as an example using a `request` and [arbitrary constructors](#arbitrary-constructors) for how to use a callable that does not require a `request`.
1. マッチしたすべてのパスパラメータは、キーワード引数として注入されます。
1. 依存関係は、連鎖したり、ネストしたりすることができます。先ほどの例で、`Person`データクラスが`PersonID`を持っていることに注目しましたか?これは、 `PersonID` が最初に呼び出され、その値が `Person.create` を呼び出す際のキーワード引数に追加されることを意味します。
-## `Request`からのオブジェクト
+## Arbitrary constructors
---:1
+Sometimes you may want to construct your injectable _without_ the `Request` object. This is useful if you have arbitrary classes or functions that create your objects. If the callable does have any required arguments, then they should themselves be injectable objects.
+
+This is very useful if you have services or other types of objects that should only exist for the lifetime of a single request. For example, you might use this pattern to pull a single connection from your database pool.
+:--:1
+```python
+class Alpha:
+ ...
+
+
+class Beta:
+ def __init__(self, alpha: Alpha) -> None:
+ self.alpha = alpha
+
+app.ext.add_dependency(Alpha)
+app.ext.add_dependency(Beta)
+
+@app.get("/beta")
+async def handler(request: Request, beta: Beta):
+ assert isinstance(beta.alpha, Alpha)
+```
+:---
+
+*Added in v22.9*
+## `Request`からのオブジェクト
+
+---:1
時には、リクエストから詳細を抽出し、前処理を行いたい場合があります。例えば、リクエストのJSONをPythonのオブジェクトにキャストし、DBクエリに基づいていくつかの追加ロジックを追加することができます。
::: warning
@@ -136,16 +156,15 @@ await request.receive_body()
- ミドルウェアを使用して、前処理と `request.ctx` への追加を行う。
- デコレータを使用して、前処理とリクエストハンドラへの引数の注入を行う。
-この例では、`compule_profile` コンストラクタで `Request` オブジェクトを使用して、偽の DB クエリを実行して `UserProfile` オブジェクトを生成し、それを返します。
- :--:1
+この例では、`compile_profile` コンストラクタで `Request` オブジェクトを使用して、偽の DB クエリを実行して `UserProfile` オブジェクトを生成し、それを返します。
+:--:1
+```python
+@dataclass
+class User:
+ name: str
- ```python
- @dataclass
- class User:
- name: str
-
- @dataclass
+@dataclass
class UserProfile:
user: User
age: int = field(default=0)
@@ -202,13 +221,10 @@ $ curl localhost:8000/profile -X PATCH -d '{"name": "Alice", "birthday": "2000-0
データベースのコネクションプールのようなものを作成して、それを `app.ctx` オブジェクトに格納するのはよくあるパターンです。これにより、アプリケーション全体でそれらを利用できるようになり、確かに便利です。しかし、1つの欠点は、型付けされたオブジェクトを扱うことができなくなることです。これを解決するために、依存性注入を使用することができます。まず、これまでの例で使ってきたような低レベルの `add_dependency` を使って、そのコンセプトを紹介します。しかし、より高いレベルの `dependency` メソッドを使用することで、より良い方法があります。
---:1
-
### `add_dependency` を使った低レベル API
これは [最後の例](#objects-from-the-request) と非常によく似た動作で、ゴールは `Request` オブジェクトから何かを抽出することです。この例では、データベースオブジェクトが `app.ctx` インスタンスに作成され、依存性注入のコンストラクタで返されています。
-
:--:1
-
```python
class FakeConnection:
async def execute(self, query: str, **arguments):
@@ -236,19 +252,15 @@ async def handler(request, conn: FakeConnection):
$ curl localhost:8000/
result
```
-
:---
---:1
-
### 上位APIを使った`dependency`
依存性インジェクションを追加する際に利用できる実際の *オブジェクト* があるので、より高レベルの `dependency` メソッドを使用することができます。これにより、パターンを書くのがより簡単になります。
このメソッドは、アプリケーションインスタンスのライフタイムを通じて存在し、リクエストに依存しないものをインジェクションしたい場合に常に使用する必要があります。サービスやサードパーティークライアント、コネクションプールなどはリクエストに依存しないので、非常に便利です。
-
:--:1
-
```python
class FakeConnection:
async def execute(self, query: str, **arguments):
@@ -270,5 +282,69 @@ async def handler(request, conn: FakeConnection):
$ curl localhost:8000/
result
```
+:---
+
+## Generic types
+Be carefule when using a [generic type](https://docs.python.org/3/library/typing.html#typing.Generic). The way that Sanic's dependency injection works is by matching the entire type definition. Therefore, `Foo` is not the same as `Foo[str]`. This can be particularly tricky when trying to use the [higher-level `dependency` method](#the-higher-level-api-using-dependency) since the type is inferred.
+
+---:1
+For example, this will **NOT** work as expected since there is no definition for `Test[str]`.
+:--:1
+```python{12,16}
+import typing
+from sanic import Sanic, text
+
+T = typing.TypeVar("T")
+
+
+class Test(typing.Generic[T]):
+ test: T
+
+
+app = Sanic("testapp")
+app.ext.dependency(Test())
+
+
+@app.get("/")
+def test(request, test: Test[str]):
+ ...
+```
:---
+
+---:1
+To get this example to work, you will need to add an explicit definition for the type you intend to be injected.
+:--:1
+```python{13}
+import typing
+from sanic import Sanic, text
+
+T = typing.TypeVar("T")
+
+
+class Test(typing.Generic[T]):
+ test: T
+
+
+app = Sanic("testapp")
+_singleton = Test()
+app.ext.add_dependency(Test[str], lambda: _singleton)
+
+
+@app.get("/")
+def test(request, test: Test[str]):
+ ...
+```
+:---
+
+## Configuration
+
+---:1
+By default, dependencies will be injected after the `http.routing.after` [signal](../../guide/advanced/signals.md#built-in-signals). Starting in v22.9, you can change this to the `http.handler.before` signal.
+:--:1
+```python
+app.config.INJECTION_SIGNAL = "http.handler.before"
+```
+:---
+
+*Added in v22.9*
diff --git a/src/ja/plugins/sanic-ext/logger.md b/src/ja/plugins/sanic-ext/logger.md
new file mode 100644
index 0000000000..13536d80d5
--- /dev/null
+++ b/src/ja/plugins/sanic-ext/logger.md
@@ -0,0 +1,28 @@
+# Background logger
+
+The background logger requires both `sanic>=22.9` and `sanic-ext>=22.9`.
+
+You can setup Sanic Extensions to log all of your messages from a background process. This requires that you not be in [single process mode](../../guide/deployment/manager.md#single-process-mode).
+
+Logging can sometimes be an expensive operation. By pushing all logging off to a background process, you can potentially gain some performance benefits.
+
+## Setup
+
+---:1
+Out of the box, the background logger is disabled. You will need to opt-in if you would like to use it.
+:--:1
+```python
+app.config.LOGGING = True
+```
+:---
+
+## How does it work
+
+When enabled, the extension will create a `multoprocessing.Queue`. It will remove all handlers on the [default Sanic loggers](../../guide/best-practices/logging.md) and replace them with a [`QueueHandler`](https://docs.python.org/3/library/logging.handlers.html#queuehandler). When a message is logged, it will be pushed into the queue by the handler, and read by the background process to the log handlers that were originally in place. This means you can still configure logging as normal and it should "just work."
+
+## Configuration
+
+| Key | Type | Default| Description |
+|--|--|--|--|
+| LOGGING | `bool` | `False` | Whether to enable this extension. |
+| LOGGING_QUEUE_MAX_SIZE | `int` | `4096` | The max size of the queue before messages are rejected. |
diff --git a/src/ja/plugins/sanic-ext/openapi/advanced.md b/src/ja/plugins/sanic-ext/openapi/advanced.md
index 23969ec2e3..46ebf6a139 100644
--- a/src/ja/plugins/sanic-ext/openapi/advanced.md
+++ b/src/ja/plugins/sanic-ext/openapi/advanced.md
@@ -1,6 +1,6 @@
# 高機能
-_ドキュメンテーションは2021年10月に追加予定_
+_ドキュメンテーションは2023年第1期に追加予定_
## CBV
diff --git a/src/ja/plugins/sanic-ext/openapi/basic.md b/src/ja/plugins/sanic-ext/openapi/basic.md
index 6672702ff3..34cb8666c2 100644
--- a/src/ja/plugins/sanic-ext/openapi/basic.md
+++ b/src/ja/plugins/sanic-ext/openapi/basic.md
@@ -6,24 +6,27 @@ Sanic ExtensionsのOpenAPI実装は、[`sanic-openapi`](https://github.com/sanic
---:1
-Sanic Extensionsは、[v3.0 OpenAPI仕様](https://swagger.io/specification/)を用いて自動生成されたAPIドキュメントをそのまま提供します。必要なのは、Sanic Extensionsをインスタンス化することによって、アプリケーションを`拡張`することだけです。
+Sanic Extensionsは、[v3.0 OpenAPI仕様](https://swagger.io/specification/)を用いて自動生成されたAPIドキュメントをそのまま提供します。あなたがする必要のあることはありません。
:--:1
```python
from sanic import Sanic
-from sanic_ext import Extend
app = Sanic("MyApp")
-Extend(app)
+
+# すべてのviewを追加する
```
:---
これで、既存のアプリケーションに基づいた美しいドキュメントがすでに生成されていることになります:
-[http://localhost:8000/docs](http://localhost:8000/docs)
+ [http://localhost:8000/docs](http://localhost:8000/docs)
+- [http://localhost:8000/docs/redoc](http://localhost:8000/docs/redoc)
+- [http://localhost:8000/docs/swagger](http://localhost:8000/docs/swagger)
+Checkout the [section on configuration](../configuration.md) to learn about changing the routes for the docs. You can also turn off one of the two UIs, and customize which UI will be available on the `/docs` route.
---:1
@@ -38,4 +41,30 @@ Extend(app)

+
+:---
+
+## Changing specification metadata
+
+---:1
+If you want to change any of the metada, you should use the `describe` method.
+
+In this example `dedent` is being used with the `description` argument to make multi-line strings a little cleaner. This is not necessary, you can pass any string value here.
+:--:1
+```python
+from textwrap import dedent
+
+app.ext.openapi.describe(
+ "Testing API",
+ version="1.2.3",
+ description=dedent(
+ """
+ # Info
+ This is a description. It is a good place to add some _extra_ doccumentation.
+
+ **MARKDOWN** is supported.
+ """
+ ),
+)
+```
:---
diff --git a/src/ja/plugins/sanic-ext/openapi/decorators.md b/src/ja/plugins/sanic-ext/openapi/decorators.md
index f0fb37ac54..a6d8173d8d 100644
--- a/src/ja/plugins/sanic-ext/openapi/decorators.md
+++ b/src/ja/plugins/sanic-ext/openapi/decorators.md
@@ -38,7 +38,7 @@ class UserProfile:
## デコレーターの定義
-### `@opanepi.definition`
+### `@openapi.definition`
`@openapi.definition`デコレーターを使用すると、パス上の操作のすべての部分を一度に定義することができます。これは、他のデコレーターと同じように操作の定義を作成できるオムニバムデコレーターです。複数のフィールド固有のデコレータを使うか、あるいは単一のデコレータを使うかは、 開発者のスタイルによります。
@@ -54,10 +54,11 @@ class UserProfile:
| `document` | **str, ExternalDocumentation** |
| `exclude` | **bool** |
| `operation` | **str** |
-| `parameter` | **dict, Parameter, *ユーザー定義モデル*, [dict], [Parameter], [*ユーザー定義モデル*]** |
-| `response` | **dict, Response, *ユーザー定義モデル*, [dict], [Response], [*ユーザー定義モデル*]** |
+| `parameter` | **str, dict, Parameter, [str], [dict], [Parameter]** |
+| `response` | **dict, Response, *ユーザー定義モデル*, [dict], [Response]** |
| `summary` | **str** |
| `tag` | **str, Tag, [str], [Tag]** |
+| `secured` | **Dict[str, Any]** |
**Examples**
@@ -118,6 +119,10 @@ class UserProfile:
@openapi.body(RequestBody(UserProfile))
```
+```python
+@openapi.body({"application/json": {"description": ...}})
+```
+
:---
:::
@@ -400,4 +405,79 @@ openapi.exclude(bp=some_blueprint)
:---
+:::
+
+:::tab secured
+
+**Arguments**
+
+| Field | Type |
+| ----------------- | ----------------------- |
+| `*args, **kwargs` | **str, Dict[str, Any]** |
+
+**Examples**
+
+---:1
+```python
+@openapi.secured()
+```
+:--:1
+:---
+
+---:1
+```python
+@openapi.tag("foo")
+```
+:--:1
+```python
+@openapi.secured("token1", "token2")
+```
+:---
+
+---:1
+```python
+@openapi.tag({"my_api_key": []})
+```
+:--:1
+```python
+@openapi.secured(my_api_key=[])
+```
+:---
+
+Do not forget to use `add_security_scheme`. See [security](./security.md) for more details.
+
+:::
+
::::
+
+
+## Integration with Pydantic
+
+Pydantic models have the ability to [generate OpenAPI schema](https://pydantic-docs.helpmanual.io/usage/schema/).
+
+---:1
+To take advantage of Pydantic model schema generation, pass the output in place of the schema.
+:--:1
+```python
+from sanic import Sanic, json
+from sanic_ext import validate, openapi
+from pydantic import BaseModel, Field
+
+class Test(BaseModel):
+ foo: str = Field(description="Foo Description", example="FOOO")
+ bar: str = "test"
+
+
+app = Sanic("test")
+
+@app.get("/")
+@openapi.definition(
+ body={'application/json': Test.schema()},
+)
+@validate(json=Test)
+async def get(request):
+ return json({})
+```
+:---
+
+*Added in v22.9*
diff --git a/src/ja/plugins/sanic-ext/templating.md b/src/ja/plugins/sanic-ext/templating.md
new file mode 100644
index 0000000000..d973f093f2
--- /dev/null
+++ b/src/ja/plugins/sanic-ext/templating.md
@@ -0,0 +1,142 @@
+# Templating
+
+Sanic Extensions can easily help you integrate templates into your route handlers.
+
+
+## Dependencies
+
+**Currently, we only support [Jinja](https://github.com/pallets/jinja/).**
+
+[Read the Jinja docs first](https://jinja.palletsprojects.com/en/3.1.x/) if you are unfamiliar with how to create templates.
+
+Sanic Extensions will automatically setup and load Jinja for you if it is installed in your environment. Therefore, the only setup that you need to do is install Jinja:
+
+```
+pip install Jinja2
+```
+
+## Rendering a template from a file
+
+There are three (3) ways for you:
+
+1. Using a decorator to pre-load the template file
+1. Returning a rendered `HTTPResponse` object
+1. Hybrid pattern that creates a `LazyResponse`
+
+Let's imagine you have a file called `./templates/foo.html`:
+
+```html
+
+
+
+
+ My Webpage
+
+
+
+ Hello, world!!!!
+
+ {% for item in seq %}
+ - {{ item }}
+ {% endfor %}
+
+
+
+
+```
+
+Let's see how you could render it with Sanic + Jinja.
+
+### Option 1 - as a decorator
+
+---:1
+The benefit of this approach is that the templates can be predefined at startup time. This will mean that less fetching needs to happen in the handler, and should therefore be the fastest option.
+:--:1
+```python
+@app.get("/")
+@app.ext.template("foo.html")
+async def handler(request: Request):
+ return {"seq": ["one", "two"]}
+```
+:---
+
+### Option 2 - as a return object
+
+---:1
+This is meant to mimic the `text`, `json`, `html`, `file`, etc pattern of core Sanic. It will allow the most customization to the response object since it has direct control of it. Just like in other `HTTPResponse` objects, you can control headers, cookies, etc.
+:--:1
+```python
+from sanic_ext import render
+
+@app.get("/alt")
+async def handler(request: Request):
+ return await render(
+ "foo.html", context={"seq": ["three", "four"]}, status=400
+ )
+```
+:---
+
+### Option 3 - hybrid/lazy
+
+---:1
+In this approach, the template is defined up front and not inside the handler (for performance). Then, the `render` function returns a `LazyResponse` that can be used to build a proper `HTTPResponse` inside the decorator.
+:--:1
+```python
+from sanic_ext import render
+
+@app.get("/")
+@app.ext.template("foo.html")
+async def handler(request: Request):
+ return await render(context={"seq": ["five", "six"]}, status=400)
+```
+:---
+
+## Rendering a template from a string
+
+---:1
+Sometimes you may want to write (or generate) your template inside of Python code and _not_ read it from an HTML file. In this case, you can still use the `render` function we saw above. Just use `template_source`.
+:--:1
+```python
+from sanic_ext import render
+from textwrap import dedent
+
+@app.get("/")
+async def handler(request):
+ template = dedent("""
+
+
+
+
+ My Webpage
+
+
+
+ Hello, world!!!!
+
+ {% for item in seq %}
+ - {{ item }}
+ {% endfor %}
+
+
+
+
+ """)
+ return await render(
+ template_source=template,
+ context={"seq": ["three", "four"]},
+ app=app,
+ )
+```
+:---
+
+::: tip
+In this example, we use `textwrap.dedent` to remove the whitespace in the beginning of each line of the multi-line string. It is not necessary, but just a nice touch to keep both the code and the generated source clean.
+:::
+
+## Development and auto-reload
+
+If auto-reload is turned on, then changes to your template files should trigger a reload of the server.
+
+## Configuration
+
+See `templating_enable_async` and `templating_path_to_templates` in [settings](./configuration.md#settings).
diff --git a/src/ja/plugins/sanic-ext/validation.md b/src/ja/plugins/sanic-ext/validation.md
index 0e8eb44554..2925400d26 100644
--- a/src/ja/plugins/sanic-ext/validation.md
+++ b/src/ja/plugins/sanic-ext/validation.md
@@ -6,7 +6,7 @@ Webアプリケーションで最もよく実装される機能の1つが、ユ
### データクラスによる検証
-[データクラス](https://docs.python.org/3/library/dataclasses.html) の導入により、Pythonは定義されたスキーマを満たすオブジェクトをとても簡単に作成することができるようになりました。しかし、標準ライブラリは型チェックの検証のみをサポートし、実行時の検証はサポート**していません**。Sanic Extensionsは`dataclasses`を使って、入力されたリクエストに対して実行時の検証を行う機能を追加します。
+With the introduction of [Data Classes](https://docs.python.org/3/library/dataclasses.html), Python made it super simple to create objects that meet a defined schema. However, the standard library only supports type checking validation, **not** runtime validation. Sanic Extensions adds the ability to do runtime validations on incoming requests using `dataclasses` out of the box. If you also have either `pydantic` or `attrs` installed, you can alternatively use one of those libraries.
---:1
@@ -60,9 +60,6 @@ $ curl localhost:8000/search\?q=python
### Pydanticを使ったバリデーション
-::: warning
-現在、PydanticモデルをサポートしているのはJSONボディの検証のみです。
-:::
Pydanticモデルの使用もできます。
@@ -109,6 +106,56 @@ $ curl localhost:8000/person -d '{"name": "Alice", "age": 21}' -X POST
:---
+### Validation with Attrs
+
+
+You can use Attrs also.
+
+---:1
+
+First, define a model.
+
+:--:1
+
+```python
+@attrs.define
+class Person:
+ name: str
+ age: int
+
+```
+
+:---
+
+---:1
+
+Then, attach it to your route
+
+:--:1
+
+```python
+from sanic_ext import validate
+
+@app.post("/person")
+@validate(json=Person)
+async def handler(request, body: Person):
+ return json(attrs.asdict(body))
+```
+:---
+
+---:1
+
+You should now have validation on the incoming request.
+
+:--:1
+
+```
+$ curl localhost:8000/person -d '{"name": "Alice", "age": 21}' -X POST
+{"name":"Alice","age":21}
+```
+
+:---
+
## 何が検証できるのか?
`validate` デコレータを使用すると、3つの場所から入力されたユーザーデータを検証することができます。JSON の本文(`request.json`)、フォームの本文(`request.form`)、そしてクエリパラメータ(`request.args`) です。
diff --git a/src/ja/plugins/sanic-testing/clients.md b/src/ja/plugins/sanic-testing/clients.md
index 40912aa10d..0bcbb4af78 100644
--- a/src/ja/plugins/sanic-testing/clients.md
+++ b/src/ja/plugins/sanic-testing/clients.md
@@ -65,7 +65,7 @@ test_client.request("/path/to/endpoint", http_method="get")
このテストクライアントは、`SanicTestClient` と同じメソッドを提供し、一般的に動作します。唯一の違いは、各コールに `await` を追加する必要があることです。
:--:
```python
-await app.test_client.get("/path/to/endpoint")
+await app.asgi_client.get("/path/to/endpoint")
```
:---