pedrotroller/api-doc
Pedrotroller/api-doc helps Laravel developers generate and serve API documentation directly from their application, turning routes and annotations into browsable reference docs that stay in sync with the code. Lightweight and easy to integrate.
First, verify the package is still viable for your stack. This package was last released in 2016, targets the NelmioApiDocBundle 2.x era (Symfony 2.7–3.x, PHP 5.5–7.x), and has effectively zero downstream users. If you're on Symfony 4+ or NelmioApiDocBundle 3.x/4.x, stop here and read the Gotchas section — the extension points it relies on no longer exist.
If you're maintaining a legacy application that already matches that stack:
src/ is the documentation. Start with the bundle class and DependencyInjection/ to see what it registers, then the annotation/handler classes to understand how translation is injected.composer require pedrotroller/api-doc
Pin the exact constraint from the last tag (1.0.x or dev-master) — there will be no patch releases.app/AppKernel.php alongside Nelmio:
new Nelmio\ApiDocBundle\NelmioApiDocBundle(),
new PedroTroller\ApiDocBundle\PedroTrollerApiDocBundle(),
Confirm the actual bundle FQCN and alias (pedro_troller_api_doc by convention) from composer.json autoload and the bundle class name.php app/console debug:container | grep -i apidoc
You're looking for a decorator or tagged handler wrapping nelmio_api_doc.extractor.@ApiDoc and replace a hard-coded description with a translation key, then request /api/doc in two locales (?locale=fr, ?locale=en) and confirm the rendered HTML differs. That single smoke test tells you whether the translator is actually being invoked or you're just seeing the raw key.Decorate, don't fork. The package's whole value is intercepting Nelmio's extraction pipeline so that @ApiDoc strings pass through Symfony's translator before reaching the formatter. In practice this means:
nelmio_api_doc.extractor.handler (the v2 extension point) whose supports() returns true and whose handle() mutates the ApiDoc object — translating description, documentation, input, output, statusCodes, and requirement descriptions.@Trans / @Translate annotation next to @ApiDoc, with the handler resolving $annotation->getMessage() through TranslatorInterface::trans() using the current request locale.Recommended workflow for a multi-locale API:
app/Resources/translations/apidoc.<locale>.yml, keyed by controller/action:
# apidoc.en.yml
api.user.list.description: "Returns a paginated list of users."
api.user.list.param.page: "Page number, 1-indexed."
_locale from the firewall or the query string; the extension should read $request->getLocale(). Verify this — a common shortcut in small bundles is to read %locale% from parameters, which breaks per-request switching.nelmio_api_doc.controller.swagger / the HTML dump at the HTTP level with Vary: Accept-Language.en and fr is enough coverage:
$client->request('GET', '/api/doc', [], [], ['HTTP_ACCEPT_LANGUAGE' => 'fr']);
$this->assertContains('Liste paginée', $client->getResponse()->getContent());
apidoc or messages) in config.yml with fallback: en so an untranslated endpoint degrades to English rather than showing a raw message id in production docs.Integration tip: if the package's annotation handler proves brittle, the same result is achievable with a thin custom handler of your own — roughly 40 lines implementing HandlerInterface, translating $annotation->getDescription() in handle(). For a package this small and this unmaintained, reimplementing the useful 10% is often the lower-risk path.
composer update as capable of breaking it silently, and pin with composer.lock committed.Document objects; 4.x removed annotations entirely in favor of PHP attributes. This package targets the 2.x @ApiDoc annotation world. There is no upgrade path. On a modern stack the equivalent is #[Model] / #[OA\...] attributes plus an injected TranslatorInterface in the controller, or translating inside a custom DescribableInterface implementation.doctrine/annotations is on a removal path (PHP 8 attributes are the replacement in Symfony 6.4+/7). A 2016 annotation-based extension compounds that debt.debug:container --tag=nelmio_api_doc.extractor.handler and debug:event-dispatcher reveal whether the service registered at all. Silent no-ops (service not tagged, tag name typo'd for your Nelmio version) are the most common failure mode — you get English text, not an error.framework.translator, so trans() returns the key. Symptom: docs show api.user.list.description verbatim. Fix by registering the bundle's Resources/translations path — Symfony auto-registers bundle translations only if the files follow the Resources/translations/<domain>.<locale>.<format> convention exactly.Vary: Accept-Language (or locale in the URL), a proxy or Symfony's HTTP cache will serve the French doc to an English client. This is the bug that bites after go-live, not during development.composer patch or vendor-fork in a day. Prefer forking into your own src/ under an internal namespace over patching vendor/ — you keep the behaviour, drop the dependency, and gain the ability to modernize the annotation reader.DescribableInterface or a small custom documentation handler. You'll write less code than you'll spend debugging this.How can I help you explore Laravel packages today?